【问题标题】:fix memory leaks with valgrind使用 valgrind 修复内存泄漏
【发布时间】:2012-10-11 09:54:36
【问题描述】:

我正在使用 c++ 并一直在使用 valgrind 来修复内存泄漏。 我正在尝试优化以下被 valgrind 描述为泄漏的代码:

void VOMC::sub_train(vector<Letter> tempLettersA, vector<Letter> tempLettersB) {
    int stateA_id = state_exists(tempLettersA);
    State *tempStateA;

    if (stateA_id != -1) {
        tempStateA = get_state_by_id(stateA_id);
    } else {
        tempStateA = new State(tempLettersA);// MEMORY LEAK - 1
        vomc.push_back(tempStateA);
    }
    int stateB_id = state_exists(tempLettersB);
    if (stateB_id != -1) {
        tempStateA->inc_state(stateB_id);
    } else {
        State* tempStateB;
        tempStateB = new State(tempLettersB);//MEMORY LEAK -2
        vomc.push_back(tempStateB);
        stateB_id = tempStateB->GetId();
        tempStateA->inc_state(stateB_id);
    }
}

对于内存泄漏 1,我收到以下消息

==11289== 4,055 (64 direct, 3,991 indirect) bytes in 1 blocks are definitely lost in   loss record 228 of 228
==11289==    at 0x402B87E: operator new(unsigned int) (vg_replace_malloc.c:292)
==11289==    by 0x807FA75: VOMC::sub_train(std::vector<Letter, std::allocator<Letter> >,    std::vector<Letter, std::allocator<Letter> >) (VOMC.cpp:952)

对于内存泄漏-2

==11289==    at 0x402B87E: operator new(unsigned int) (vg_replace_malloc.c:292)
==11289==    by 0x807FB16: VOMC::sub_train(std::vector<Letter, std::allocator<Letter> >,     std::vector<Letter, std::allocator<Letter> >) (VOMC.cpp:968)

我可以删除这些指针吗?这将消除我的泄漏,但是您可以看到指针被推入堆栈,目标是将它们保留在堆栈中但消除泄漏。

编辑 -1:添加字母和状态定义:

class Letter {

public:
    Letter();
    Letter(Helper *helper);
    ~Letter();

    void add_note(RawNote r);
    void evaluate_letter(double eigthNoteDuration);
    void setNotePositionAccordingToLetter();
    void empty_notes();
    LetterPattern getPattern() const;
    void setPattern(LetterPattern pattern);
    bool isEmpty();
    vector<RawNote> getRawNotes() const;
    void setRawNotes(vector<RawNote> rawNotes);

    bool has_note_no_velocity(RawNote* r1);
    bool has_note_with_velocity(RawNote* r1);

private:
    vector<LetterPattern> *allPossibleNotes;
    vector<RawNote> rawNotes;
    LetterPattern pattern;

};

class State {
public:
State(); //should not be used, it is only for testing
State(vector<Letter> letters);
virtual ~State();
int GetId() const;
void SetId(int id);
vector<Letter> GetLetters() const;
void SetLetters(vector<Letter> letters);
void AddLetters(vector<Letter> letters);
void inc_state(int state_id);
void print_state_letters();
bool has_state(int state_id);
void print_connected_states();
void print_sorted_states();
vector<string> get_rhythm_as_string();
map<int, double> GetConnected_states() const;
map<int, double> connected_states;
vector< pair <int, double > > vector_sorted_connected_states;
void bubblesort_vector_descending(vector< pair <int, double > > *v_sort);
int get_connected_state_stochastically();
static int id_generator;
CustomNumberDist *normal_dist;
int id_from_file; //only used on load of a file
private:
int id;
vector<Letter> letters;
};

【问题讨论】:

  • 帮自己一个忙,将指针更改为智能指针。我在&lt;memory&gt; 中推荐shared_ptr
  • 有时你必须delete[]他们,否则他们会被泄露。我们不知道你在程序的其余部分做了什么,或者为什么你必须在 vomc 中存储指针,所以很难给出建议。
  • @stefan 等等,你怎么知道所有权是共享的?我错过了什么?你有帖子上没有的信息吗? @Potney 帮自己一个忙...考虑先不要使用任何智能级别的指针,然后再使用 unique_ptr
  • @PotneySwitters 不,这不是真的。当拥有它的指针被销毁时,该对象被销毁。除非您将其设为 const(因此不可转让),否则您可以将所有权转移到堆栈中,然后在堆栈销毁时将其销毁。
  • @PotneySwitters:使用new的主要原因是为了完全控制对象的生命周期,从而超越“在声明处出生,在作用域结束处死亡”的生命周期堆栈分配的对象得到。如果堆栈分配足够好,那么不要使用new,你不会有内存泄漏;)我们可以看到LetterState的定义吗?

标签: c++ memory-leaks valgrind


【解决方案1】:

valgrind 能告诉你的只是泄漏的来源。它无法告诉您对delete 的缺失调用在哪里——它缺失了。

一种解决方案是在将指针从堆栈中弹出后删除指针,并让VOMC::~VOMC() 删除堆栈中保留的所有元素。这种方法只有在 VOMC 类“拥有”堆栈上的每个对象时才有效。如果堆栈还包含指向 State 对象的指针,而这些指针以某种方式归某个其他对象所有,则此方法无法工作。

使用原始指针容器处理混合所有权有点困难。处理混合了所有权的原始指针容器的一种方法是将owned_by 指针添加到State 类(或包含的任何内容)。现在你的类VOMC 只删除那些属于this 的对象。这里有一个架构问题:它散发着代码气味。 SWIG 中存在与此方法类似的情况,有时您需要将 thisown 属性设置为 false。当我看到这样的东西时,我的代码气味传感器会超标。

第三种方法是摆脱那些原始指针。而不是原始指针的集合,使您的 vomc 数据成员成为某种智能指针实例的对象(不是指针)的集合。这是处理原始指针的现代方法,而不是使用原始指针。

【讨论】:

    猜你喜欢
    • 2017-07-29
    • 2021-09-27
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 2020-03-31
    • 2016-03-15
    • 2014-04-09
    • 1970-01-01
    相关资源
    最近更新 更多