如何避免这种内存泄漏?

时间:2016-04-21 12:41:29

标签: c++ methods memory-leaks free

这是我的代码:

void MIDITest::CreateNoteBlock() {
    IMidiMsgExt* midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(57, 100, 0, 0, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(60, 100, 0, tickSize * 38, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(62, 100, 0, 0, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(65, 100, 0, tickSize * 32, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(57, 0, tickSize * 111, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(60, 0, tickSize * 111, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(62, 0, tickSize * 75, 0);
    queuedNotes.insert(*midiMessage);

    midiMessage = new IMidiMsgExt;
    midiMessage->MakemidiMessageMsg(65, 0, tickSize * 105, 0);
    queuedNotes.insert(*midiMessage);
}   

所以每个new运算符都会分配一块内存。

我应该在queuedNotes中的任何free之后使用insert吗?或者它会在void函数返回后释放? (即CreateNoteBlock的括号)。

或者,每次midiMessage指针指向新的IMidiMsgExt时,我都可以“重复使用”?

4 个答案:

答案 0 :(得分:6)

答案是不要使用new。创建具有自动存储持续时间的对象

IMidiMsgExt midiMessage;

然后您可以继续致电MakemidiMessageMsg并将邮件的副本插入multiset

midiMessage.MakemidiMessageMsg(57, 100, 0, 0, 0);
queuedNotes.insert(midiMessage);
midiMessage.MakemidiMessageMsg(60, 100, 0, tickSize * 38, 0);
queuedNotes.insert(midiMessage);
//...

现在multiset有一份所有消息的副本,并且在函数midiMessage的末尾被销毁,并且不需要进行内存管理。

如果IMidiMsgExt有一个类似于MakemidiMessageMsg的构造函数,您可以在其中构建一个完整的消息,那么您可以进一步使用它,并使用类似

的内容
queuedNotes.insert(IMidiMsgExt(57, 100, 0, 0, 0));
queuedNotes.insert(IMidiMsgExt(60, 100, 0, tickSize * 38, 0));

现在我们甚至不需要midiMessage

答案 1 :(得分:5)

您是来自Java还是C#背景?在C ++中,您不必使用new来创建对象,只需声明它们可以正常工作:

IMidiMsgExt midiMessage;
midiMessage.MakemidiMessageMsg(57, 100, 0, 0, 0);
queuedNotes.insert(midiMessage);

要么(这是我建议的解决方案),要么你必须明确释放对象:

IMidiMsgExt* midiMessage = new IMidiMsgExt;
midiMessage->MakemidiMessageMsg(57, 100, 0, 0, 0);
queuedNotes.insert(*midiMessage);
delete miniMessage;

答案 2 :(得分:1)

使用new动态分配IMidiMsgExt似乎是多余的。你可以直接在堆栈上分配它(没有指针),然后当你的方法返回时它会被销毁。即:

void MIDITest::CreateNoteBlock() {
    IMidiMsgExt midiMessage();
    midiMessage.MakemidiMessageMsg(57, 100, 0, 0, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(60, 100, 0, tickSize * 38, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(62, 100, 0, 0, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(65, 100, 0, tickSize * 32, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(57, 0, tickSize * 111, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(60, 0, tickSize * 111, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(62, 0, tickSize * 75, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt();
    midiMessage.MakemidiMessageMsg(65, 0, tickSize * 105, 0);
    queuedNotes.insert(midiMessage);
}

答案 3 :(得分:1)

尝试使您的API更像C ++。

在堆栈中使用一个对象,而不是在堆中创建许多新对象。

void MIDITest::CreateNoteBlock() {
    IMidiMsgExt midiMessage;

    midiMessage.MakemidiMessageMsg(57, 100, 0, 0, 0);
    queuedNotes.insert(midiMessage);

    midiMessage.MakemidiMessageMsg(60, 100, 0, tickSize * 38, 0);
    queuedNotes.insert(midiMessage);

    // ...
}

在构造函数中初始化对象。为operator = (const IMidiMsgExt&)定义IMidiMsgExt

void MIDITest::CreateNoteBlock() {
    IMidiMsgExt midiMessage(57, 100, 0, 0, 0);
    queuedNotes.insert(midiMessage);

    midiMessage = IMidiMsgExt(60, 100, 0, tickSize * 38, 0);
    queuedNotes.insert(midiMessage);

    // ...
}

我想,insert()期望const IMidiMsgExt&。所以你可以直接传递刚刚初始化的对象:

void MIDITest::CreateNoteBlock() {
    queuedNotes.insert({57, 100, 0, 0, 0});
    queuedNotes.insert({60, 100, 0, tickSize * 38, 0});

    // ...
}
顺便说一句:你应该更喜欢使用例如std::queue<> queuedNotes。然后,您将不会使用insert(),而是使用push()emplace()emplace()的优点是,它构造容器中的对象而不是先创建它然后将其复制到容器中:

void MIDITest::CreateNoteBlock() {
    queuedNotes.emplace(57, 100, 0, 0, 0);
    queuedNotes.emplace(60, 100, 0, tickSize * 38, 0);

    // ...
}

此外,您的typename IMidiMsgExt向我发出信号,表示您正在尝试模仿C ++中的C#思维。这是可能的,但通常它不是首选的解决方案。从你的问题我不太了解你的类树和提供建议的基本要求,但在C ++中通常是代码味道。