IT TIP

C에서 const 포인터를 해제 할 수 없습니다.

itqueen 2020. 11. 21. 08:29
반응형

C에서 const 포인터를 해제 할 수 없습니다.


어떻게 해제 할 수 const char*있습니까? 을 (를) 사용하여 새 메모리를 할당했는데 해제 malloc하려고 할 때 항상 "호환되지 않는 포인터 유형"오류가 발생합니다.

이를 일으키는 코드는 다음과 같습니다.

char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);

free(str); // error here

여러 사람이 정답을 게시했지만 어떤 이유로 계속 삭제합니다. 상수가 아닌 포인터로 캐스트해야합니다. freea void*가 아니라을 사용합니다 const void*.

free((char*)str);

코드가 반전되었습니다.

이:

char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);

다음과 같이 표시되어야합니다.

const char* name="Arnold";
char* str=(char*)malloc(strlen(name)+1);

const저장 유형 (동적 또는 정적) 할당 된 후에는 메모리 블록을 수정하지 않을 것을 컴파일러를 알려줍니다. 메모리를 해제하면 수정됩니다. malloc ()의 반환 값캐스팅 할 필요는 없지만 그저 제쳐두고 있습니다.

메모리를 동적으로 할당하고 (의 길이에 따라 수행하는 작업 name) 컴파일러에 사용할 의도가 없음을 알리는 데 거의 사용되지 않습니다. 참고 사용하여 다음에 뭔가 쓰는 의미 (선택 사항) 나중에 해제.

다른 스토리지 유형으로 캐스트한다고해서 스토리지 유형을 뒤집 었다는 사실이 수정되지는 않습니다. :) 경고 메시지가 사라지고 무언가를 알려줍니다.

코드가 반전되면 (해야하는대로) free()실제로 할당 한 메모리를 수정할 수 있으므로 예상대로 작동 합니다.


const에 대한 포인터를 malloc하는 것은 의미가 없습니다. 그 내용을 수정할 수 없기 때문입니다 (추악한 해킹없이).

하지만 FWIW에서는 gcc가 다음에 대한 경고 만 표시합니다.

//
// const.c
//

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    const char *p = malloc(100);

    free(p);
    return 0;
}

$ gcc -Wall const.c -o const
const.c: In function ‘main’:
const.c:8: warning: passing argument 1 of ‘free’ discards qualifiers from pointer target type
$ 

어떤 컴파일러를 사용하고 있습니까?


당신이 무료 할 경우가 있습니다 const*. 그러나 동일한 기능에 할당 / 서명하지 않는 한 그렇게하고 싶지 않습니다. 그렇지 않으면 물건을 부술 수 있습니다. 실제 예제는 아래 코드를 참조하십시오. const함수 선언에 사용 하여 인수의 내용을 변경하지 않음을 보여줍니다. 그러나 해제해야하는 소문자 중복 (strdup)으로 다시 할당 됩니다.

char* tolowerstring(const char *to_lower)
{
    char* workstring = strdup(to_lower);
    for(;workstring != '\0'; workstring++)
        *workstring = tolower(workstring);
    return workstring;
}

int extension_checker(const char* extension, const char* to_check)
{
    char* tail = tolowerstring(to_check);
    extension = tolowerstring(extension);

    while ( (tail = strstr( tail+1, extension)) ) { /* The +1 prevents infinite loop on multiple matches */
        if ( (*extension != '.' ) && ( tail[-1] != '.'))
            continue;
        if ( tail[strlen(extension)] == '\0') {
            free(tail);
            free( (char*) extension);
            return 1;
        }
    }
    free(tail);
    free( (char *) extension);
    return 0;
}

malloc 포인터를 const로 캐스팅하는 데는 목적이 없습니다. const 포인터를 사용하는 함수는 전달 된 메모리를 해제 할 책임이 없어야합니다.


내가 틀릴 수도 있지만 문제는에 있다고 생각합니다 const. 포인터를 상수가 아닌 것으로 캐스팅합니다.

free((char *) p);

const당신 과 함께 말하기 때문에 : 이 포인터가 가리키는 데이터를 변경하지 마십시오 .


Several answers have suggested simply casting to char*. But as el.pescado wrote above,

casting const to non-const is a symptom of code smell.

There are compiler warnings that guard against this, such as -Wcast-qual in gcc, which I find very useful. If you really have a valid case for freeing a const pointer (contrary to what many have written here, there are valid cases, as pointed out by nlstd), you could define a macro for that purpose like this:

#define free_const(x) free((void*)(long)(x))

This works at least for gcc. The double cast makes the logic -Wcast-qual not detect this as "casting const away". Needless to say, this macro should be used with care. Actually it should only be used for pointers allocated in the same function.


You cannot free const char * because it is const. Store pointers received from malloc in non-const pointer variables, so that you can pass them to free. You can pass char * arguments to functions taking const char * arguments but opposite is not always true.

void foo (const char *x);
char *ptr = malloc (...);
foo (ptr);
free (ptr);

If you are talking about pure C and you are in complete control of the memory allocation you can use the following trick to cast (const char *) to (char *) which will not give you any warning in compiler:

const char *const_str = (const char *)malloc(...);
char *str = NULL;

union {
  char *mutable_field_p;
  const char *const_field_p;
} u;

u.const_field_p = const_str;
str = u.mutable_field_p;

Now you can use free(str); to free the memory.

But BEWARE that this is evil beyond words and should be only used in strictly controlled environment (e.g. library which allocates and frees strings, but doesn't want to allow user to modify them) Otherwise you will end up with your program crashing when someone provides compile time "STRING" to your free function.


I think the real answer is that free should take a const pointer argument and NULL should be defined as a const pointer. This seems to be a bug in the standards. Freeing a const pointer should be implemented as follows:

free(p);
p = NULL;

I don't see how a compiler could generate incorrect code in this case, the const pointer p is no longer accessible, so it doesn't matter if the object it pointed to is const, valid, whatever else. Its const so there can't be any dirty copies in registers or anywhere else. It is valid to set a const pointer to another value, and the fact that that value is NULL doesn't matter because the previous value is no longer accessible.


If you take a look at the signature of free function , free always takes void* ptr as an argument therefore you need to cast it to the appropriate type i.e. free((void *)str); free does not allow const pointers to be deallocated directly therefore you need to cast it to non const type


I think even if you cast the pointer to a non-const, the result of free will depends on the implementation. Normally const was designed for variable that you don't want to modify !!

참고URL : https://stackoverflow.com/questions/2819535/unable-to-free-const-pointers-in-c

반응형