我如何释放一个const char*
?我使用malloc
分配了新的内存,在尝试释放它时,总是会收到 "不兼容的指针类型" 错误。
引起这个错误的代码大致如下:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
free(str); // error here
有几个人发布了正确的答案,但出于某种原因他们一直在删除它。你需要将其转换为非const指针;free
使用的是void*
,而不是const void*
:
free((char*)str);
const
转换为非const
是代码异味的一种征兆。 - el.pescado - нет войнеconst int
,并离开它被声明的作用域,是否可以?这样会“释放”自动变量,释放资源并使指向它的指针无效。只是free
需要非const参数是一种怪异现象,并不是来自上级的命令。在极少数情况下,如果你的指针只有一个非const的操作就是释放,那么实际上使用const指针(然后进行强制类型转换)可能比非const指针更有益,因为你可能会意外地修改非const指针。 - Steve Jessopchar* 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()
将按预期工作,因为您实际上可以 修改 分配的内存。将指针分配到常量是没有意义的,因为您将无法修改其内容(除非使用丑陋的技巧)。
尽管如此,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
$
char const* s = strdup("hello"); free(s);
。 - bobbogo有些情况下,您可能需要释放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指针的函数都不应该负责释放传递给它的内存。
struct foo { const char *bar; ... }
这样的代码怎么处理呢?这表示指向 foo->bar
的内存应该被视为不可变的(而 struct foo
的其他成员可能是可变的)。这对于保证程序的正确性非常有用。但当对象首次初始化时,可能需要对 bar
进行 malloc。如果要释放这样的对象,则需要一种方法来释放 bar
。 - uncleremusstruct foo { union { const char *bar; char *__bar; }; }
可以工作。 - uncleremusbar
元素,而可能会传递foo
对象并可能修改其他成员。即使在拥有结构体的代码中,使用const
来保护bar
免受错误修改也是可取的。在析构函数中只需要强制转换掉const
即可。 - uncleremusconst
转换为 char*
。但正如 el.pescado 上面所写的,const
到非 const
是代码味道的一种症状。-Wcast-qual
,我发现这非常有用。如果您确实有一个释放 const
指针的有效情况(与许多人在此处写的相反,nlstd指出了一些有效情况),您可以定义一个宏来完成此操作,如下所示:#define free_const(x) free((void*)(long)(x))
这至少适用于gcc。双重转换使逻辑 -Wcast-qual
不会将其检测为“去除const的强制转换”。不用说,这个宏应该小心使用。实际上,它只应用于在同一函数中分配的指针。
free(p);
p = NULL;
我可能错了,但我认为问题在于const
。像这样将指针转换为非常量:
free((char *) p);
因为使用 const
,你就是在说:不要改变这个指针所指向的数据。
free
函数不会改变指针本身,它释放指针所指向的内存块。这是语言规范中的一个错误。free
函数应该清晰地接受一个常量指针。 - Axel Gneitingconst
表示你不能更改存储对象的内容,而不是指针实际的值...释放所指向的内存是非常重大的变化!(顺便说一句,认为规范是错误的[已经错误了30多年],突然发现你是正确的,而所有审查委员会成员都是错误的,似乎有点自负,不是吗?) - fortranconst
表示此位置上的数据不应更改。但是,如果您释放内存,则可以覆盖此位置上的数据,因此更改数据。 - Felix Klingconst 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;
void free(const void* p);
。在C++中已经被修复(使用delete
)。 - MSaltersconst char*
是很有意义的。提问者真的需要我们的批准才能遇到问题吗?;-) - Steve Jessopstr
,就无法通过str
来更改它,这意味着当malloc()
抓取它时,内存中包含的内容是永久的。不加转换就无法将名称复制到其中。 (此外,将字符串文字分配给char *
不好,因为尝试修改字符串文字是未定义的行为。我认为您只是混淆了const
。) - David Thornleyconst char *
可能会在填充内容后从char *
转换而来,例如从const char* foo() { char* s = malloc(...); strcpy(s, ...); return s; }
这样的函数中。 - musiphilconst
指针在哪里? - haccks