1

我正在使用 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;
};
4

1 回答 1

2

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

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

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

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

于 2012-10-21T13:48:32.110 回答