使用 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&lt;std::string&gt;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 newed。这是一条硬性规定,没有例外。 data[i] 从来不是 newed,它是一个指向 string 内部缓冲区的 c_str() 指针(强制转换)。即使那个指针仍然有效(记住,这并不是因为这个c_str() 来自哪里的那个参数不再存在),这个delete 仍然是无效的。

总结:这里显示的构造函数和析构函数代码存在几个基本问​​题,您需要解决所有这些问题。

【讨论】:

你真的是我的救星。非常感谢。

以上是关于使用 delete[] 调试断言失败的主要内容,如果未能解决你的问题,请参考以下文章

调试断言失败:_CrtIsValidHeapPointer(pUserData)

调试断言失败

调试断言失败

从发布模式更改为调试模式时出现“调试断言失败”错误

调试断言失败!表达式:result_pointer!=nullptr

Visual Studio 2019 调试断言失败