我有简单的代码,
#include "stdafx.h"
#include <malloc.h>
int main()
{
char *p = (char*) malloc(10);
p = "Hello";
free(p);
return 0;
}
此代码在终止时给出运行时异常。以下是错误信息,
Debug Assertion失败!
程序:... \ my documents \ visual studio 2010 \ Projects \ samC \ Debug \ samC.exe 文件:f:\ dd \ vctools \ crt_bld \ self_x86 \ crt \ src \ dbgheap.c 行:1322
表达式:_CrtIsValidHeapPointer(pUserData)
有关程序如何导致断言的信息 失败,请参阅关于断言的Visual C ++文档。
答案 0 :(得分:6)
p = "Hello";
使p
指向字符串文字,并丢弃先前分配的值。你不能free
字符串文字。你不能修改它。
如果您希望p
保留该字符串,请使用
char* p = "Hello";
或
char p[] = "Hello";
如果您打算修改它。
两者都不需要free
。
答案 1 :(得分:4)
这是在malloc为char指针分配的内存中编写字符串的方法。
strcpy(p, "Hello");
替换
行p = "Hello";
strcpy
一个&amp;你的程序会正常工作。
你还需要
#include <string.h>
malloc
返回指向已分配内存的指针。假设地址是95000(只是我抽出的随机数)。
所以在malloc -p之后会保存地址95000
包含95000
的p是内存地址,当你完成内存后需要将其传递给free。
但是,下一行p = "Hello";
将字符串文字“Hello”(表示存在于地址25000
)的地址放入p。
因此,当您执行free(p)
时,您正试图释放未被malloc分配的25000
。
OTOH,当你strcpy
时,你将字符串“Hello”复制到从p开始的地址(即95000
)。在strcpy之后p
仍为95000
。
free(p)
释放了正确的记忆。
您也可以避开malloc
并使用
char *p = "Hello";
但是,在此方法中,您无法修改字符串。
即。如果在此之后你执行*p = 'B'
将字符串更改为Bello
,则它将变为未定义的操作。 malloc
方式并非如此。
相反,如果您使用
char p[] = "Hello";
或
char p[10] = "Hello";
你得到一个可修改的字符串,不需要free
d。
答案 2 :(得分:2)
p = "Hello";
free(p);
由于Hello
是静态分配的,因此您无法free
。我不确定为什么你只是通过将指针改为另一个指针来分配一些内存,但这没有任何效果。如果你这样做:
int i = 1;
i = 2;
i
没有曾经拥有1
的记忆,它现在拥有2
。类似地,p
没有内存,它曾经拥有指向你分配的内存的指针。它现在拥有一个指向不可变常量的指针。
答案 3 :(得分:1)
这是一个很好的。
char序列“hello”是常量,因此在堆或堆栈中放置,但在.bss / .data段中。当你执行p="hello"
时,你将p指向该段中字符串hello的地址,而不是使用malloc
在堆上分配的内存。当你转到free
时,它试图释放.bss / .data段中的内存,并自然失败。
你可能想要的是像strcpy(p,"hello");
这样的东西,它遍历“hello”中的每个字符并将其放在p指向的内存中。基本上在内存地址p。
答案 4 :(得分:0)
如果要将字符串“Hello”的内容复制到分配的内存中,则需要使用strcpy
:
strcpy(p, "Hello");
该行
p = "Hello";
将字符串文字“Hello”的地址分配给指针p
,覆盖从malloc
返回的指针值,因此在您调用时崩溃{ {1}}。