【问题标题】:Debug Assertion Failure even when using delete[]即使使用 delete[] 也调试断言失败
【发布时间】:2014-11-11 15:10:05
【问题描述】:

我是编程初学者,最近写了这段代码

#include<iostream>
using namespace std;


void removeAllCharacters(char * , char * );
void printArray(char*);

void deleteArrays(char*,char*);

int main()
{
            char * source,*remove;
            source=new char[18];
            remove=new char[10];

            source="Hello how are you";
            remove="Hi Its me";

            removeAllCharacters(source,remove);
            printArray(source);

            deleteArrays(source,remove);
            system("pause");
            return 0;
}

void removeAllCharacters(char * source, char * remove)
{
            int N1=strlen(source)+1;
            int N2=strlen(remove)+1;

            bool arr[128] = {false};

            for(int i=0;i<N2-1;i++)
            {
                arr[remove[i]]=1;
            }

            char *newSource=new char[N1];

            for(int i=0,j=0;i<N1-1;i++)
            {
                if(arr[source[i]]==0)
                {
                    newSource[j++]=source[i];
                }
            }

            delete  [] source;
            source=newSource;
            newSource=0;
}

void printArray(char* arr)
{
            int N=strlen(arr)+1;

            for(int i=0;i<N;i++)
            {
                cout << arr[i];
            }

            cout << endl << endl;
}

void deleteArrays(char* arr1,char*arr2)
{
            delete [] arr1;
            arr1=0;
            delete[]arr2;
            arr2=0;
}

我试过调试,发现只有 错误发生在 delete[] 源;在 removeCharacters 函数中。我尝试在网上寻找解决方案,但找不到。 为什么会出现此错误?错误是因为我从 main 分配了动态内存,但我正在从函数中删除它?

【问题讨论】:

  • 你看到了什么错误?
  • 我不确定这是什么意思:arr[remove[i]]=1,但它会导致未定义的行为。
  • 使用std::string,你的代码就可以工作了。您将指针与对象混淆了。

标签: c++ visual-studio-debugging


【解决方案1】:

new[]的返回值是一个指针值。无论发生什么,当您调用 delete[] 时,必须使用完全相同的指针值。

显然这会违反上面的规则:

    source=new char[18];
    remove=new char[10];

    source="Hello how are you";
    remove="Hi Its me";

您使用new[] 进行分配,但将返回的值替换为字符串文字的值。换句话说,调用delete[] 所需的指针值现在消失了。

这是你应该做的一个例子:

    char str1[] = "Hello how are you";
    char str2[] = "Hi Its me";
    source=new char[sizeof(str1)];
    remove=new char[sizeof(str2)];
    strcpy(source, str1);
    strcpy(remove, str2);

请注意,我们创建了两个使用数据初始化的缓冲区。然后我们小心地为字符(加上终止的 null)分配足够的存储空间,而不是计算字符并可能出错。

然后strcpy 函数将字符复制到另一个缓冲区。

你还有另一个错误:

source=newSource

您会立即看到返回时source 没有您刚刚分配的指针。原因是 source 是一个值参数,因此是函数的本地参数——分配给它不会对传递给函数的实际值做任何事情,因为任何赋值都只是在函数时冒烟返回。

另外,如果您是 C++ 编程的初学者,您可以开始使用 std::string 而不是 char* 来处理字符串数据。使用 new[] 创建字符串是 C++ 中的一种恐龙方法。请改用std::string。你真的应该努力避免像这样创建字符串:

 char *newSource=new char[N1];

这会导致内存泄漏,有时还会导致类似意大利面条的逻辑来跟踪分配的内存,以便delete[] 正常运行。此外,大多数(如果不是全部)提到的这些问题都消失了。分配工作,没有内存泄漏等。

【讨论】:

    【解决方案2】:
        source="Hello how are you";
        remove="Hi Its me";
    

    这是错误的。正确的做法是:

        strcpy( source, "Hello how are you" );
        strcpy( remove, "Hi Its me" );
    

    您不能“删除”常量字符串。您可以删除使用“new”分配的数组/内存。

    【讨论】:

    • 在像“char”这样的简单类型的情况下,没有[]的删除没有区别。如果数组的元素是对象并且需要显式调用其析构函数,则括号是必需的。
    • @i486--char* chars = new char[100]; delete chars; 是未定义的行为。在实践中它可能会起作用,或者可能只有 100 字节分配中的一个字节被释放(取决于实现的工作方式)。但规则是,如果您使用new[],请确保您也使用delete[]
    • @i486 我很确定即使在简单的内置类型的情况下,您也应该使用与用于分配存储的新运算符匹配的删除运算符。如果通过 new[] 分配,则应通过 delete[] 删除,除非您喜欢未定义的行为。
    • 如果它是用new[] 分配的,那么用delete 释放它是错误的。 100% 简单明了。
    • 不完全同意这一点。 new[] 之后的 delete[] 是对于还没有完全理解的学生的简单规则。实际上,delete 以与 delete[] 相同的方式为 new char[100] 释放内存。如果数组是 ...new my_class[100] 那么会有很大的不同 - delete[] 将被称为数组中每个对象的析构函数,然后将释放内存 (100 * sizeof(my_class)) 字节和使用 delete 将不会执行析构函数 - 只会释放内存...
    【解决方案3】:

    源是按值传递的。调用 delete [] source 不会对 main 函数中的 source 产生任何影响。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-31
      • 2020-12-31
      • 2019-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多