1

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

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

4

5 回答 5

7

您正在分配单个字符而不是数组。利用:

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

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

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

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

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

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

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

  1. 使用更高级别的构造,例如std::string. 他们为您进行内存管理,使您不必处理低级字符串函数。
  2. 例如,使用 Microsoft 的(非标准)安全变体 - strcpy_s。这些函数也会占用缓冲区的大小,如果不足则失败 - 不会造成任何损害。
  3. 使用(标准)strncpy,将缓冲区的大小作为最后一个参数传递,并检查返回值以查看已复制了多少字符。与前面的建议一样,指定错误的缓冲区大小仍然会造成损坏。
  4. 请记住,如果您想自己动手,C++ 会很乐意给您一把指向下方的枪。必须小心处理原始缓冲区、指针和低级字符串函数。语言不会把你从自己的错误中拯救出来。
于 2012-07-12T11:20:48.660 回答
4

因为您通过尝试将 4 个字符“asdf”(如果计数为空终止符实际上是 5 个)填充到一个只能容纳 1 个字符的内存块中,从而破坏了堆:

strcpy(ptr,"asdf");

更新:

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

ptr=new char[5];

分配 5char秒(字符串的 4 个字符 + 每个字符串末尾应有 1 个空终止符),并释放分配的内存,您应该使用

delete[] ptr;

[]意味着您要删除一个字符数组,而不仅仅是一个字符。

于 2012-07-12T11:21:34.663 回答
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");
于 2012-07-12T11:20:01.823 回答
1

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

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

于 2012-07-12T11:33:51.077 回答
1

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

然后尝试将大小为 5 的字符串复制到ptrusing strcpy.

您可能想知道为什么它没有在strcpy调用本身时崩溃。原因是strcpy不对分配的大小执行任何验证,因此由于缓冲区溢出而导致未定义的行为

参考: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 中,您可以使用安全的替代方法strcpy, strcpy_s.

参考:strcpy_s、wcscpy_s、_mbscpy_s

于 2012-07-12T11:46:21.347 回答