为什么这段代码在释放指针时会给出运行时异常

时间:2013-01-08 12:16:36

标签: c runtime

我有简单的代码,

#include "stdafx.h"
#include <malloc.h>
int main()
{
  char *p = (char*) malloc(10);
  p = "Hello";

  free(p);

  return 0;
}

此代码在终止时给出运行时异常。以下是错误信息,


Microsoft Visual C ++调试库

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 ++文档。

(按“重试”调试应用程序)

中止重试忽略

5 个答案:

答案 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。

创建字符串“hello”的副本

答案 4 :(得分:0)

如果要将字符串“Hello”的内容复制到分配的内存中,则需要使用strcpy

strcpy(p, "Hello");

该行

p = "Hello";

将字符串文字“Hello”的地址分配给指针p,覆盖从malloc返回的指针值,因此在您调用时崩溃{ {1}}。