我怎样才能释放一个const char*
?我使用 分配了新内存malloc
,当我尝试释放它时,我总是收到错误“不兼容的指针类型”
导致这种情况的代码类似于:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
free(str); // error here
有几个人发布了正确的答案,但他们出于某种原因不断删除它。您需要将其转换为非常量指针;free
需要 a void*
,而不是 a 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()
将按预期工作,因为您实际上可以修改您分配的内存。
malloc 指向 const 的指针是没有意义的,因为您将无法修改其内容(没有丑陋的 hack)。
不过 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 指针的函数都不应该负责释放传递给它的内存。
几个答案建议简单地转换为char*
. 但正如 el.pescado 上面写的,
强制转换
const
为 non-const
是代码异味的症状。
有一些编译器警告可以防止这种情况发生,例如-Wcast-qual
在 gcc 中,我发现它非常有用。如果您确实有释放const
指针的有效案例(与许多人在这里写的相反,有有效案例,正如 nlstd 指出的那样),您可以为此目的定义一个宏,如下所示:
#define free_const(x) free((void*)(long)(x))
这至少适用于 gcc。双重转换使逻辑-Wcast-qual
不会将其检测为“将 const 转换掉”。不用说,这个宏应该小心使用。实际上它应该只用于在同一函数中分配的指针。
我可能是错的,但我认为问题出在const
. 将指针转换为非常量,例如:
free((char *) p);
因为和const
你说:不要改变这个指针指向的数据。
如果您正在谈论纯 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”编译到您的自由功能。
我认为真正的答案是 free 应该接受一个const
指针参数并且NULL
应该被定义为一个const
指针。这似乎是标准中的一个错误。释放const
指针应按如下方式实现:
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.
如果您查看 free function 的签名,free 总是将 void* ptr 作为参数,因此您需要将其转换为适当的类型,即 free((void *)str); free 不允许直接释放 const 指针,因此您需要将其转换为非 const 类型
你不能自由const char *
,因为它是const
。将收到的指针存储malloc
在非常量指针变量中,以便您可以将它们传递给free
. 您可以将参数传递char *
给接受const char *
参数的函数,但相反的情况并非总是如此。
void foo (const char *x);
char *ptr = malloc (...);
foo (ptr);
free (ptr);
我认为即使您将指针转换为非常量,free will 的结果也取决于实现。通常 const 是为您不想修改的变量设计的!