【问题标题】:C++ memory leak (valgrind)C++ 内存泄漏 (valgrind)
【发布时间】:2016-03-15 03:42:14
【问题描述】:

Valgrind 声称我间接失去了记忆;让我烦恼的是,我不知道为什么会这样。

不确定这是误报还是我只是不理解某些指针分配或其他内容。

我是不是在这里失忆了?如果有,为什么?

Valgrind 报告:

==24392== 21 bytes in 2 blocks are indirectly lost in loss record 1 of 3
==24392==    at 0x4028699: operator new[](unsigned int) (in        /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==24392==    by 0x804B41D: Perishable::load(std::basic_fstream<char,        std::char_traits<char> >&) (Perishable.cpp:42)
==24392==    by 0x804C504: sict::PosApp::loadRecs() (PosApp.cpp:139)
==24392==    by 0x804D58E: sict::PosApp::run() (PosApp.cpp:393)
==24392==    by 0x8049337: main (milestone4.cpp:8)

这是第 42 行:

std::fstream& Perishable::load(std::fstream& stream) {
    char    mysku[MAX_SKU_LEN + 1];
    char    mynam[100];
    bool    mytax;
    double  myprice;
    int     myqty;
    int     date[5]; 

    stream.getline(mysku, 100, ',');
    sku(mysku);
    stream.getline(mynam, 100, ',');

    name(mynam);//bytes indirectly lost

这里是 name() [完整注释]

void Item::name(char *name){
    delete[] _name; //..............Just in case it points to something.
                    //..............Note: How could I possibly be losing memory with this line here??
    int x = strlen(name); //........Grab the length of the new input

    if (_name == '\0') {//..........If it was empty, ie. its the first assignment
        _name = new char[x + 1];//..Allocate the space, +1 for null char
    }

    for (int i = 0; i < x; i++) {//.Copy
        _name[i] = name[i];
    }

    _name[x]   = '\0';//............Yeah, its manual termination. I should maybe use strcpy
}

编辑>>>这里是析构函数

Item::~Item() {
    std::cout << "called destructor";
    delete[] _name;
    _name = '\0';
}

编辑>>复制构造函数和赋值运算符

//Copy Constructor
Item::Item(const Item& copyfrom){
    (*this) = copyfrom;

}

//Member operators
Item& Item::operator=(const Item &myitem) {
    if (!myitem.isEmpty()){
        init((*this), myitem._sku, myitem._name, myitem._price, myitem._taxed);
        this->_quantity = myitem._quantity;

    }
    return (*this);
}

void Item::init(Item &obj, char const sku[], char const name[], double priced, bool taxed) {

    int length = strlen(name);
    int skulength = strlen(sku);

    obj._price = priced;
    obj._taxed = taxed;
    obj._quantity = 0;
    obj._name = new char[length+1]; //+1 for the null which wasn't counted. Huge pain debugging that.


    for (int i = 0; i < length; i++) {

        obj._name[i] = name[i];

        if (i < skulength) {//redundanc


            obj._sku[i] = sku[i];
        }
    }

    obj._name[length]   = '\0';
    obj._sku[skulength] = '\0';

}

【问题讨论】:

  • 这是编译器痛苦的尖叫,试图告诉你使用std::string
  • 哈哈。大概。不幸的是,这是一项学校作业,我不会像那样狡猾,呵呵。
  • _name 在哪里定义?此外,delete [] _name 看起来很吓人,尤其是当您之后使用它时(可能是双重释放等)。 `_name == '\0' 看起来也很错误(应该是 == nullptr 吗?还是 _name[0] == '\0'?这显然是删除后未定义的行为......)
  • @bigcodeszzer 我敢打赌,使用给您的相同规则创建自己的课程没有任何限制。您不会使用 std::string 类,并且您仍在使用 new []delete [] 仅在代码的不同部分。再说一遍,如果你知道什么是复制构造函数、赋值运算符和析构函数的作用,你仍然可以按照规则正确编写代码。
  • @bigcodeszzer 如果您正在复制或分配Item 对象,那么如果没有用户定义的复制构造函数和赋值运算符,您的代码将无法正常工作。您需要向我们展示您在什么上下文中使用 Item 对象。而且不管老师说什么,如果您正在执行这些操作中的任何一个,您的代码无法正常工作(分配,复制构造)。所以如果你没有被教过这些操作,那就抱怨吧。我可以很容易地导致您的课程基本上很少做的泄漏(同样,如果您没有编码所需的操作)。

标签: c++ memory-leaks valgrind dynamic-memory-allocation delete-operator


【解决方案1】:

我只看到:

Item::~Item() {
    std::cout << "called destructor";
    delete[] _name;
    // Don't reassign
}

void Item::init(Item &obj, char const sku[], char const name[], double priced, bool taxed) {
    // ...
    if (obj._name == nullptr /* 0 */) {
        obj._name = new char[length+1]; 
        // What if it's not null?
    } else {
        // Do you want to delete and new up a char?
    }
}

另外,对我来说,使用非常量引用很可怕。我认为在 init 中更新 obj._name 是最大的问题,没有任何先发制人的检查。

【讨论】:

  • 具体检查什么?
  • 我编辑了答案。如果它不为空并且您对其进行了新的更新,那么您不会在空闲存储中分配新空间之前释放旧块。我找到了我认为相关的this
【解决方案2】:

如果您确实必须使用new 和裸指针(提示:几乎没有人这样做),那么您需要确保_name 的所有者在不再需要它时释放它。

正确的位置可能~Item()析构函数,但是如果没有其余代码,就很难确定。

【讨论】:

    猜你喜欢
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    • 2013-06-24
    • 2019-07-02
    • 2021-11-28
    • 2020-06-23
    相关资源
    最近更新 更多