删除指针的问题(指向的内容)

时间:2012-07-12 11:18:36

标签: c++ delete-operator

如何删除我在以下代码中指定的指针:

char* ptr;
ptr=new char(65);   // memory for one char is created and is assigned 'A'
strcpy(ptr,"asdf"); // how can string of length 4 chars are copied
delete ptr;         // why am I getting debug error of Heap corruption detected

我正在使用Visual C ++ 2005

5 个答案:

答案 0 :(得分:7)

您正在分配一个char而不是一个数组。使用:

char* ptr;
ptr=new char[65];
strcpy(ptr,"asdf");
delete[] ptr;

就像现在一样,你将第一个a写入已分配的char,其余的则写入从未分配给你的任意内存。运行时检测到(在调试版本中)并抱怨。

对我的答案中的问题部分发表评论:

C ++没有任何机制来识别问题代码中的潜在错误。编译器知道传递给strcpy的缓冲区大小的唯一方法是使用静态分析,这可能有效,也可能无效。但即使这样,编译器也不知道strcpy的语义。因此,在编译时,它无法警告您错误。

现在,当缓冲区在运行时传递给strcpy时,strcpy无法判断缓冲区有多大。所以它只是假设调用者提供了一个合适的缓冲区,并继续复制。如果幸运的话,溢出分配的缓冲区将导致由于写入未分配的页面而立即崩溃。如果没有,你会得到内存损坏。

您获得的错误是调试版本中使用的机制的结果:内存管理器分配的字节数比您要求的多一些,并在其上写入特殊模式。然后,当释放分配的内存时,它会检查该模式是否仍然存在。如果没有,它会抱怨用户的代码已写入其中。在发布版本中,您没有那些额外的检查,并且此类错误可能会导致损坏而不会被发现。

避免此类情况的唯一方法是编写更安全的代码:

  1. 使用更高级别的构造,例如std::string。他们为您进行内存管理,使您不必处理低级字符串函数。
  2. 例如,使用Microsoft的(非标准)安全变体 - strcpy_s。这些函数也会占用缓冲区的大小,如果不足则会失败 - 不会造成任何损害。
  3. 使用(标准)strncpy,将缓冲区的大小作为最后一个参数传递,并检查返回值以查看已复制的字符数。与之前的建议一样,指定错误的缓冲区大小仍会造成损坏。
  4. 请记住,如果你想拍自己的脚趾,C ++很乐意给你一把指点枪。处理原始缓冲区,指针和低级字符串函数必须小心处理。这种语言不会让你免于犯错误。

答案 1 :(得分:4)

因为你通过尝试将4个字符“asdf”(实际上是5,如果count null终结符)填充到一个只能通过这样做的1个字符的内存块中来破坏堆:

strcpy(ptr,"asdf");

更新

您应该根据需要(或更多)分配尽可能多的内存。如果你需要将4个字符的字符串复制到一个内存块中,你应该确保内存块足够大以保留它,因此,在你的情况下,你应该使用

ptr=new char[5];

分配5 char s(每个字符串应该有4个字符串+ 1个空终结符),并释放分配的内存,你应该使用

delete[] ptr;

[]表示您要删除一个字符数组,而不只是一个字符。

答案 2 :(得分:1)

这实际上是错的。你想要:

ptr=new char[65];   // memory for one char is created and is assigned 'A'
strcpy(ptr,"asdf"); // how can string of length 4 chars are copied
delete[] ptr;   

更好:

char ptr[65];
strcpy(ptr,"asdf");

最好的:

std::string str("asdf");

答案 3 :(得分:1)

这是内存损坏的典型案例。堆是具体的。 ptr只分配了1个字节,并且您正在执行溢出1个字节的字符串复制操作。

您的程序可能不一定立即崩溃,但会导致随机崩溃或未定义的行为。

答案 4 :(得分:1)

首先,您为ptr分配了一个字节。并为其指定了“A”。

然后尝试使用ptr将大小为5的字符串复制到strcpy

你可能想知道为什么它没有在strcpy电话本身崩溃。原因是strcpy未对分配大小执行任何验证,因此导致缓冲区溢出导致未定义行为

参考:Segmentation fault in strcpy

char* ptr;
ptr=new char[5];   // I see no point in assigning 'A' as you replace it in next statement.
strcpy(ptr,"asdf");
delete[] ptr;         // delete[] is used as memory is allocated for arrays of elements.

此外,在Visual Studio 2005中,您可以使用strcpystrcpy_s的安全替代方案。

参考:strcpy_s, wcscpy_s, _mbscpy_s