我在测试一些代码时遇到了一个可怕的错误。我发现它是由调用free(p_current_item->s)
引起的,其中p_current_item
是链表中的节点,s是它包含的char *。我通过调用方法addItem(node,char *)来创建节点,该方法只是将元素添加到列表中:p_head=addItem(p_head,"this gets added");
困扰我的是:
1)为什么我需要释放元素中包含的字符串。我知道当s被声明为char* s = snprintf(s,(size_t),30,"this gets added");
时(这是在我的类示例中完成的方式)是必要的,但为什么这是必要的 - 是否可以将属性包含在结构中(在本例中为linkedList)在释放struct本身时释放?
2)当我试图释放显式声明的s的值时发生了什么
3)我是否需要以其他方式释放s的价值?
谢谢: - )
答案 0 :(得分:4)
您只能free
使用malloc
系列电话分配的内存。
用双引号封装的字符串是编译时常量。它们与指令文本一起导入到运行时程序中。因此,那些尚未动态分配。
同样snprintf
返回生成的字符串的长度,而不是指向它的指针。正确的用法是:
size_t length = snprintf(s,(size_t)30,"this gets added");
1)如果使用s
,malloc
或该家庭的其他电话分配,则您只需要免费calloc
。例如char* s = malloc(1024);
2)free("constant string");
最多会导致分段违规,因为您尝试释放尚未由malloc
系列调用分配的内存。通常这是未定义的行为。
3)你不需要释放常量字符串,它们是你文本的一部分,即使你想这样做也不能被释放。
答案 1 :(得分:0)
当您在代码中声明s
时,它不会在堆中分配。只有当您需要释放使用free()
或malloc
在堆中动态分配的内存时,才会调用calloc
- 这在您的代码中并非如此。
答案 2 :(得分:0)
像"this gets added"
这样的文字字符串在可执行文件中分配了固定内存地址,就像全局和static
变量一样。你不需要也不能解除它们。
如果你的情况是清理功能不知道是否需要调用free()
,有时可能需要调用,最好的解决方案是制作基于堆的所有内容副本并始终致电free()
。方便的是,您可以使用strdup()
:
p_head=addItem(p_head, strdup("this gets added"));
答案 3 :(得分:0)
1)为什么我需要释放元素中包含的字符串。一世 知道s被声明为char * s =时是必要的 snprintf(s,(size_t),30,“这被添加”); (这是怎么做的 在我的班级例子中)但为什么这是必要的 - 是否有可能 结构中包含的属性(在本例中为linkedList) 在释放struct本身时释放?
您需要释放已分配的内存。
char *s = snprintf(s, ...)
做错了。你需要:
char *s = NULL; // Declare memory -- and initialize it to NULL just to be safe.
// This way, using unallocated memory will be easily spotted.
s = malloc(30); // Allocate the memory
if (NULL == s) // Check that it has been allocated.
{
abort();
}
// Use the memory: sprintf into s
snprintf(s, "My name is %s", 30, "John");
// Use the result
printf("%s\n", s);
free(s); // Free the memory
s = NULL; // If you're really paranoid, NULL out its pointer.
// This way, also using no-longer-allocated memory will be spotted.
你也可能遇到 valgrind ,发现他是一个不灵活但又很有价值的朋友。
2)当我试图释放s的值时发生了什么 明确声明
没什么好的:-)。内存分配器发现了一个错误,并迅速崩溃了你的程序以避免更糟糕的情况发生。
3)我是否需要以其他方式释放s的价值?
如果你已经分配了它,是的。见上文。