【问题标题】:How can this piece of C++ code get memory leak?这段C++代码怎么会出现内存泄漏?
【发布时间】:2016-08-02 10:52:31
【问题描述】:

我编写了一些 C++ 代码来实现我自己的堆栈。但是当我使用valgrind查看时,它说可能存在内存泄漏。查了很久还是没找到。

这是代码:

#ifndef RE_STACK_H
#define RE_STACK_H

#include <cstdlib>
#include "general.h"

template <typename T>
class Stack {
private:
    T* bottom;
    T* top;
    T* sentinel;
    uint32 size;
public:
    Stack(uint32 size = 30);
    ~Stack();
    void push(const T&);
    T pop();
    void expand();
};

template <typename T>
Stack<T>::Stack(uint32 size) :size(size){
    bottom = top = static_cast<T*>(malloc(size * sizeof(T)));
    sentinel = bottom + size * sizeof(T);
}

template <typename T>
Stack<T>::~Stack() {
    while (top-- != bottom){
        top->~T();
    }
    free(bottom);
}

template <typename T>
void Stack<T>::push(const T& item){
    if(top == sentinel){
        expand();
    }
    new(top++)T(item);
}

template <typename T>
T Stack<T>::pop() {
    if(bottom == top){
        return 0;
    }
    T re = *--top;
    top->~T();
    return re;
}

template <typename T>
void Stack<T>::expand() {
    size *= 2;
    uint32 temp = top - bottom;
    bottom = static_cast<T*>(realloc(bottom, size * sizeof(T)));
    top = bottom + temp;
    sentinel = bottom + size * sizeof(T);
}
#endif //RE_STACK_H




#include <iostream>
#include "NTL/Stack.h"

int main() {
    return 0;
}

这是来自valgrind的错误信息:

==33519== HEAP SUMMARY:
==33519==     in use at exit: 22,216 bytes in 190 blocks
==33519==   total heap usage: 256 allocs, 66 frees, 27,992 bytes allocated
==33519== 
==33519== 2,064 bytes in 1 blocks are possibly lost in loss record 58 of 63
==33519==    at 0x10000817C: malloc_zone_malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==33519==    by 0x1005E1EFD: _objc_copyClassNamesForImage (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D5182: protocols() (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D5093: readClass(objc_class*, bool, bool) (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D2C13: gc_init (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005DA24E: objc_initializeClassPair_internal(objc_class*, char const*, objc_class*, objc_class*) (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005E7132: layout_string_create (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D583C: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D5300: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D52E9: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D52E9: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==33519==    by 0x1005D52E9: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==33519== 
==33519== LEAK SUMMARY:
==33519==    definitely lost: 0 bytes in 0 blocks
==33519==    indirectly lost: 0 bytes in 0 blocks
==33519==      possibly lost: 2,064 bytes in 1 blocks
==33519==    still reachable: 0 bytes in 0 blocks
==33519==         suppressed: 20,152 bytes in 189 blocks
==33519== 
==33519== For counts of detected and suppressed errors, rerun with: -v
==33519== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 18 from 18)

看过几部cmet,想说明一下:

  1. 我使用malloc()free()而不是newdelete,因为我想将内存分配和类构造的过程分开,你可以在我的析构函数中看到,我释放内存那里。并且每次我pop() 一个项目时,我都会使用类的析构函数来确保它被正确销毁,但是我没有释放内存,因为我以后可能会使用它

    1234563
  2. 我知道我没有遵循 3/5 规则,实际上我并没有完成代码,我稍后会编写复制构造函数和赋值运算符,我只是想测试一下代码不大。

  3. 请不要说代码是垃圾,你只看一眼就知道我用的是malloc();如果你看过 STL 的源代码,你就会明白分配器是如何工作的

【问题讨论】:

  • 注意到 Valgrind 输出中似乎没有引用您的代码?这意味着您没有内存泄漏。 “泄漏”很可能是误报,来自一些动态分配内存的初始化代码,这些内存应该在程序的生命周期内存在。
  • 您没有复制构造函数和赋值运算符 -- 请参阅rule of three/five/zero
  • @hfhc2, @adnan_e: 在malloced 内存上调用placement new 和显式析构函数就可以了。
  • 致 OP:sentinel 的初始化在我看来不正确,不应该只是 sentinel = bottom + size
  • Werrrrghhh...malloc?为什么?!

标签: c++ memory-leaks


【解决方案1】:

最后我认为是因为valgrind。不知道为什么,即使我写了这么简单的代码,我也报错了......

int main(int argc, char* argv[]){
    return 0;
}

无论如何,感谢那些帮助我找出错误的人:

  1. sentinel 只需添加大小...
  2. realloc 不能帮我调用析构函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    相关资源
    最近更新 更多