无法释放 C 中的 const 指针

发布于 2024-09-01 15:05:21 字数 240 浏览 7 评论 0原文

如何释放 const char*?我使用 malloc 分配了新内存,当我尝试释放它时,我总是收到错误“不兼容的指针类型”

导致此问题的代码如下:

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

free(str); // error here

How can I free a const char*? I allocated new memory using malloc, and when I'm trying to free it I always receive the error "incompatible pointer type"

The code that causes this is something like:

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

free(str); // error here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

故事灯 2024-09-08 15:05:21

有几个人发布了正确的答案,但他们出于某种原因不断删除它。您需要将其转换为非常量指针; free 采用 void*,而不是 const void*

free((char*)str);

Several people have posted the right answer, but they keep deleting it for some reason. You need to cast it to a non-const pointer; free takes a void*, not a const void*:

free((char*)str);
好久不见√ 2024-09-08 15:05:21

你的代码是反的。

应该

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() 将按预期工作,因为您实际上可以修改您分配的内存。

Your code is reversed.

This:

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

Should look like this:

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

The const storage type tells the compiler that you do not intend to modify a block of memory once allocated (dynamically, or statically). Freeing memory is modifying it. Note, you don't need to cast the return value of malloc(), but that's just an aside.

There is little use in dynamically allocating memory (which you are doing, based on the length of name) and telling the compiler you have no intention of using it. Note, using meaning writing something to it and then (optionally) freeing it later.

Casting to a different storage type does not fix the fact that you reversed the storage types to begin with :) It just makes a warning go away, which was trying to tell you something.

If the code is reversed (as it should be), free() will work as expected since you can actually modify the memory that you allocated.

樱花细雨 2024-09-08 15:05:21

malloc 指向 const 的指针是没有意义的,因为您将无法修改其内容(没有丑陋的黑客)。

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
$ 

您使用什么编译器?

It makes no sense to malloc a pointer to const, since you will not be able to modify its contents (without ugly hacks).

FWIW though, gcc just gives a warning for the following:

//
// 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
$ 

What compiler are you using ?

窝囊感情。 2024-09-08 15:05:21

在某些情况下,您想要释放 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;
}

There are cases you want to free a const*. However you don't want to do it unless you allocate/asign it in the same function. Else you are likely to break things. See the code below for a real world example. I use const in the function declarations to show that I am not changing the content of the arguments. However it is reassigned with a lowercased duplicate (strdup) that needs to be freed.

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;
}
闻呓 2024-09-08 15:05:21

将 malloc 指针强制转换为 const 没有任何意义。任何采用 const 指针的函数都不应该负责释放传递给它的内存。

There's no purpose in casting a malloc'd pointer to const. Any function that takes a const pointer should not be responsible for freeing the memory that was passed to it.

流殇 2024-09-08 15:05:21

有几个答案建议简单地转换为 char*。但正如 el.pescado 上面所写的那样,

const 转换为非 const 是代码异味的症状。

有编译器警告可以防止这种情况,例如 gcc 中的 -Wcast-qual,我发现它非常有用。如果您确实有释放const指针的有效案例(与许多人在这里写的相反,有有效案例,正如指出的那样)通过 nlstd),您可以为此目的定义一个宏,如下所示:

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

这至少适用于 gcc。双重强制转换使得逻辑 -Wcast-qual 不会将其检测为“强制转换 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.

南笙 2024-09-08 15:05:21

我可能是错的,但我认为问题出在 const 上。将指针强制转换为非常量,例如:

free((char *) p);

因为对于 const,您会说:不要更改该指针指向的数据

I could be wrong but I think the problem lies in const. Cast the pointer to non-const like:

free((char *) p);

Because with const you say: Don't change the data this pointer points to.

浮世清欢 2024-09-08 15:05:21

我认为真正的答案是 free 应该采用 const 指针参数,而 NULL 应该定义为 const 指针。这似乎是标准中的一个错误。释放 const 指针应按如下方式实现:

free(p);
p = NULL;

我不明白编译器如何在这种情况下生成不正确的代码,const 指针 p 不再可访问,因此它指向的对象是否 const、有效或其他都无关紧要。它是 const,因此寄存器或其他任何地方都不能有任何脏副本。将 const 指针设置为另一个值是有效的,并且该值为 NULL 的事实并不重要,因为以前的值不再可访问。

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.

回首观望 2024-09-08 15:05:21

如果您正在谈论纯 C 并且您完全控制内存分配,您可以使用以下技巧将 (const char *) 转换为 (char *),这不会在编译器中给您任何警告:

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;

现在您可以使用 free (str);来释放内存。

但请注意,这是难以言喻的邪恶,只能在严格控制的环境中使用(例如,分配和释放字符串的库,但不允许用户修改它们),否则当有人提供时,您最终会导致程序崩溃将时间“STRING”编译为您的自由函数。

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.

罪歌 2024-09-08 15:05:21

如果你看一下 free 函数的签名,free 总是将 void* ptr 作为参数,因此你需要将其转换为适当的类型,即 free((void *)str);
free 不允许直接释放 const 指针,因此您需要将其转换为非 const 类型

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

池木 2024-09-08 15:05:21

我认为即使你将指针转换为非常量,自由意志的结果也取决于实现。通常 const 是为您不想修改的变量设计的!

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 !!

自在安然 2024-09-08 15:05:21

您无法释放 const char *,因为它是 const。将从 malloc 接收的指针存储在非常量指针变量中,以便可以将它们传递给 free。您可以将 char * 参数传递给采用 const char * 参数的函数,但相反的情况并不总是如此。

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

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文