2

我有简单的代码,

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

  free(p);

  return 0;
}

此代码在终止时给出运行时异常。下面是最简单的错误,


Microsoft Visual C++ 调试库

调试断言失败!

程序:...\我的文档\visual studio 2010\Projects\samC\Debug\samC.exe 文件:f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c 行:1322

表达式:_CrtIsValidHeapPointer(pUserData)

有关您的程序如何导致断言失败的信息,请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)

中止 重试 忽略

4

5 回答 5

6

p = "Hello";p指向一个字符串文字并丢弃先前分配的值。您不能free使用字符串文字。你不能修改它。

如果您想p保留该字符串,只需使用

char* p = "Hello";

或者

char p[] = "Hello";

如果你打算修改它。

两者都不需要free

于 2013-01-08T12:18:04.987 回答
5

这就是在 malloc 分配的内存中将字符串写入 char 指针的方式。

strcpy(p, "Hello");

换行

p = "Hello";

strcpy你的程序将正常工作。

你还需要

#include <string.h>

malloc返回一个指向已分配内存的指针。假设地址是 95000(只是我取出的一个随机数)。

所以在 malloc - p 之后将保存地址95000 p 包含95000的是内存地址,当你完成内存时需要传递给 free 。

但是,下一行将p = "Hello";字符串文字“Hello”(即存在于 address 处25000)的地址放入 p 中。

因此,当您执行时,free(p)您试图释放25000不是由 malloc 分配的。

OTOH,当 you 时strcpy,您将字符串“Hello”复制到从 p 开始的地址中(即95000)。在 strcpy 之后p仍然存在。95000

free(p)释放正确的内存。

你也可以避免malloc和使用

char *p = "Hello";

但是,在此方法中,您不能修改字符串。

即,如果在此之后您*p = 'B'将字符串更改为Bello,它将成为未定义的操作。情况并非如此malloc

如果相反,您使用

char p[] = "Hello";

或者

char p[10] = "Hello";

你得到一个不需要freed 的可修改字符串。

于 2013-01-08T12:21:39.410 回答
2
p = "Hello";
free(p);

由于Hello是静态分配的,因此您不能free这样做。我不确定你为什么分配一些内存只是为了通过将指针更改为另一个指针来丢弃指针,但这没有任何效果。如果你这样做:

int i = 1;
i = 2;

i没有记忆它曾经持有 a 1,它2现在持有 a 。同样,p没有内存,它曾经持有指向您分配的某些内存的指针。它现在拥有一个指向不可变常量的指针。

于 2013-01-08T12:18:44.987 回答
1

这是一个不错的。字符序列“hello”是恒定的,因此既不在堆上也不在堆栈上,而是在 .bss/.data 段中。当你这样做时,p="hello"你让 p 指向该段中字符串 hello 的地址,而不是你在堆上分配的内存malloc。当您转到freep 时,它会尝试释放 .bss/.data 段中的内存,并且自然会失败。

您可能想要的是strcpy(p,"hello");遍历“hello”中的每个字符并将其放置在 p 指向的内存中。本质上是在内存地址 p 处创建字符串“hello”的副本。

于 2013-01-08T12:23:35.397 回答
0

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

strcpy(p, "Hello");

线

p = "Hello";

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

于 2013-01-08T13:51:29.210 回答