【问题标题】:C++ Corrupted HeapC++ 损坏的堆
【发布时间】:2016-08-10 20:26:56
【问题描述】:

当 main 方法返回时,我的程序似乎抛出了一个关于损坏堆的 rune-time 异常。我已经采取了适当的预防措施来避免这种情况发生,包括复制构造函数。谁能解释一下为什么会这样?

MyString.cpp

#include "MyString.h"
#include <cstdio>
#include <Windows.h>

MyString::MyString() {
    str = (char*)malloc(sizeof(char));
    *str = '\0';
}

MyString::MyString(char* src) {
    int size = sizeof(char)*(strlen(src) + 1);
    str = (char*)malloc(size);
    strcpy_s(str, size, src);
}


MyString MyString::operator+(char* add) {
    int addSize = sizeof(char)*strlen(add);
    int fullSize = sizeof(char)*(strlen(str) + 1) + addSize;
    str = (char*)realloc(str, fullSize);
    char* temp = str;
    temp += strlen(str);
    strcpy_s(temp, addSize + 1, add);
    return *this;
}

MyString::~MyString() {
    if (str)
        free(str);
}

MyString::MyString(const MyString &arg) {
    int size = sizeof(char) * (strlen(arg.str) + 1);
    str = (char*)malloc(size);
    strcpy_s(str, size, arg.str);
}

main.cpp

#include <iostream>
#include "MyString.h"
using namespace std;


int main(int argc, char *argv[]) {
    MyString test = MyString("hello!");
    test = test + " world";
    cout << test.toString() << endl;
    cout << strlen(test.toString()) << endl;
    system("pause");
    return 0; //runtime error here
}

【问题讨论】:

  • toString 定义在哪里
  • “MyString.h”中有什么?
  • 我鼓励使用newdelete 而不是mallocfree
  • 应该在test = test + " world"; 收到编译器警告,因为" world"const char *,而不是char *。与MyString test = MyString("hello!"); 相同
  • 通常我会同意@grigor,但是他们稍后使用的realloc 技巧会有点讨厌。

标签: c++ memory malloc free realloc


【解决方案1】:

我正在根据@user4581301 的建议修复我的帖子:

您应该修改您的加法运算符重载,以便它生成一个新对象并像这样实现赋值运算符重载:

MyString operator+(char* add) const {
    int thisSize = sizeof(char)*strlen(str);
    int addSize = sizeof(char)*(strlen(add) + 1);
    int fullSize = thisSize + addSize;

    char* tempStr = (char*)malloc(fullSize);
    strcpy_s(tempStr, fullSize, str);
    strcpy_s(tempStr + thisSize, fullSize, add);

    return MyString(tempStr);
}

MyString& operator=(const MyString& assign){

    int assignSize = sizeof(char)*(strlen(assign.str) + 1);

    str = (char*)realloc(str, assignSize);

    strcpy_s(str, assignSize, assign.str);

    return *this;
}

【讨论】:

【解决方案2】:

你必须了解Rule Of Three

使用隐式赋值运算符,当旧对象被销毁时,新对象使用已释放的指针,稍后它会再次尝试释放它。

【讨论】:

  • 你很可能是正确的。 test = test + " world"; 很可能是致命的,但我们需要看到 operator= 的实现,如果有的话,可以确定。复制构造函数和析构函数看起来符合三规​​则,我们还没有看到赋值运算符。在那之前,我们能做的就是猜测。
猜你喜欢
  • 2011-12-03
  • 2011-08-03
  • 2013-09-29
  • 2010-10-17
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 2010-11-15
  • 2011-06-09
相关资源
最近更新 更多