使用 delete[] 调试断言失败
Posted
技术标签:
【中文标题】使用 delete[] 调试断言失败【英文标题】:Debug Assertion fail using delete[] 【发布时间】:2021-02-10 03:40:52 【问题描述】:我查看了许多类似的问题,但他们都说要做我正在做的事情。 我有一个 char** 变量,它基本上只是一个字符串数组,我只是想释放内存。
CStringArray::~CStringArray()
delete[] eachSize;
for (int i = 0; i < size; ++i)
delete[] data[i];
delete[] data;
运行时我总是得到一个 Debug Assertion Failed 错误。
这就是数据的定义方式。
CStringArray::CStringArray(vector<string> strings)
size = strings.size() + 1;
data = new char* [size];
// Set last element to null.
data[size - 1] = NULL;
// Convert each string to a cstring.
for (int i = 0; i < size - 1; ++i)
data[i] = (char*) strings.at(i).c_str();
【问题讨论】:
指针和数组是不同的。data
是如何定义的?
我更新了问题以了解如何定义数据。它被声明为 char** 变量。
@Lvl1Lasagna 我不明白你为什么要使用CStringArray
,而你已经在使用std::vector<std::string>
。 CStringArray
的目的是什么?
@PaulMcKenzie 是的,这对我来说似乎也很奇怪。这是我的操作系统课的一个程序,我的教授要求我们改变打字。我想这可能是为了将来使用 cmd 传递给 C 程序。
如果您将 size
存储为类成员,则无需将最后一个元素设置为 null,因为您始终知道由于大小而实际拥有多少个元素。
【参考方案1】:
在你的构造函数中:
CStringArray::CStringArray(vector<string> strings)
strings
,这里是这个构造函数的参数。当构造函数返回时,strings
向量被销毁。它变得没有了。它不复存在。它加入了无形的合唱团。它成为一个前参数。这就是所有函数的所有参数(包括构造函数)的工作方式。它们是它们自己的对象,拥有自己的生命,当它们的功能回归时,它们就会自然而然地结束。无论这个向量中有什么,当构造函数返回时,它都会完全消失。
data[i] = (char*) strings.at(i).c_str();
c_str()
是指向string
内部缓冲区的指针。当字符串消失并被销毁,或被修改,这里c_str()
返回的指针将不再有效,任何使用它的尝试都会变成未定义的行为.
这正是c_str()
返回const
的原因,以及您必须将其显式转换为char *
以消除编译器错误的原因。 C++ 错误告诉您代码存在真正的问题,并且尝试通过显式强制转换来修复编译器错误很少是正确的做法,而且几乎总是最终产生的问题多于解决的问题。指向const
的指针是一个警告标志:请勿触摸。你不能碰这个。在这个转瞬即逝的时间点,除了阅读其中的内容之外,您无法做任何其他事情。仅此而已。但这还不是问题的结束;另外,在析构函数中:
delete[] data[i];
您只能delete
new
ed。这是一条硬性规定,没有例外。 data[i]
从来不是 new
ed,它是一个指向 string
内部缓冲区的 c_str()
指针(强制转换)。即使那个指针仍然有效(记住,这并不是因为这个c_str()
来自哪里的那个参数不再存在),这个delete
仍然是无效的。
总结:这里显示的构造函数和析构函数代码存在几个基本问题,您需要解决所有这些问题。
【讨论】:
你真的是我的救星。非常感谢。以上是关于使用 delete[] 调试断言失败的主要内容,如果未能解决你的问题,请参考以下文章
调试断言失败:_CrtIsValidHeapPointer(pUserData)