2011-07-04 56 views
6

我正在通過編寫程序將MIDI文件轉換爲Lilypond源文件來學習C++。 我的程序由兩個主要部分組成:錯誤顯然是由尚未執行的代碼引起的

  • 一個MIDI文件解析器,它創建一個名爲MidiFile的對象。
  • 一個採用MidiFile對象並將其轉換爲Lilypond源的轉換器。

今天我已經開始編碼轉換器了,當我測試它時,出現了一個奇怪的錯誤:程序在拋出異常後死亡,更具體地說是HeaderError,這意味着MIDI文件中的頭塊不像預期的那樣。這似乎並不奇怪,但只有在錯誤代碼之後添加一行代碼纔會出現此錯誤!我想補充的main()函數,以便更好地解釋自己

#include <iostream> 
#include "midiToLyConverter.hpp" 

int main(){ 

      // a queue to store notes that have not yet been shut down 
    using MidiToLyConverter::Converter::NoteQueue; 
      // representation of a note 
    using MidiToLyConverter::Converter::Note; 
      // the converter class 
    using MidiToLyConverter::Converter::Converter; 
      // the midifile class 
    using Midi::MidiFile; 
      // representation of a midi track 
    using Midi::MidiTrack; 
      // representation of a midi event 
    using Midi::MidiEvents::Event; 

    Parser::Parser parser = Parser::Parser(); // parser class 
    parser.buildMidiFile(); // builds the midi file from a .mid 
    Midi::MidiFile* midiFile = parser.getMidiFile(); // gets the MidiFile object 

    // iterates over all the tracks in the MidiFile 
    while(midiFile->hasNext()){ 
     std::cout<< "==========\n"; 
     MidiTrack* track = midiFile->nextTrack(); 
     // iterates over all events in a track 
     while(track->hasNext()){ 
      Event* event = track->nextEvent(); 
      if (event->getEventType() == Midi::MidiEvents::NOTE_ON || 
       event->getEventType() == Midi::MidiEvents::NOTE_OFF 
      ) 
       // print the event if it's a note on or off 
       event->print(); 
     } 
    } 

    return 0; 
} 

用我的main()這樣的,一切工作正常,但是,如果我添加buildMidiFile和while循環之間的東西,功能buildMidiFile拋出異常! ! 即使它是一個完全不相關的指令!

#include <iostream> 
#include "midiToLyConverter.hpp" 

int main(){ 

    using MidiToLyConverter::Converter::NoteQueue; 
    using MidiToLyConverter::Converter::Note; 
    using MidiToLyConverter::Converter::Converter; 
    using Midi::MidiFile; 
    using Midi::MidiTrack; 
    using Midi::MidiEvents::Event; 


    Parser::Parser parser = Parser::Parser(); // parser class 
    parser.buildMidiFile(); // THE EXCEPTION IS THROWN HERE 
    Midi::MidiFile* midiFile = parser.getMidiFile(); // gets the MidiFile object 

      // adding this causes the exception to be thrown by the function 
      // buildMidiFile() called 5 lines above! 
    std::vector<bool>* vec = new std::vector<bool>(); 

    // iterates over all the tracks in the MidiFile 
    while(midiFile->hasNext()){ 
     std::cout<< "==========\n"; 
     MidiTrack* track = midiFile->nextTrack(); 
     // iterates over all events in a track 
     while(track->hasNext()){ 
      Event* event = track->nextEvent(); 
      if (event->getEventType() == Midi::MidiEvents::NOTE_ON || 
       event->getEventType() == Midi::MidiEvents::NOTE_OFF 
      ) 
       // print the event if it's a note on or off 
       event->print(); 
     } 
    } 

    return 0; 
} 

我不能解釋自己這是可能的。因此,如果任何人有想法或建議,所有的幫助將不勝感激:)如果有幫助,我可以發佈其他類和/或功能的源代碼。

+4

聞起來像一個記憶中,它被調用的代碼某處覆蓋。通過聲明一個新的局部變量,你正在改變堆棧佈局,現在不同的東西被覆蓋。 – Torp

+0

聽起來像堆棧腐敗給我,但我看不到在哪裏或如何。 – Justin

+3

這可能是一個問題'Parser :: Parser parser = Parser :: Parser();'因爲它創建了一個臨時的'Parser'對象並將其複製到'parser'。嘗試僅使用「解析器解析器」;。 –

回答

3

解決!正如在對這個問題的評論中指出的那樣,這是由某種內存損壞引起的問題。作爲建議我使用的存儲checher(Valgrind的),並發現這是一個非常愚蠢的錯誤:我只是忘了在初始化變量的循環,像

for (int i; i < limit ; i++) 

,這導致了奇怪的錯誤: - )將i初始化爲0解決了這個問題,現在程序可以將Parser對象放置在堆棧或堆上。

因此,我建議其他人會出現類似的問題,使用內存檢查器來控制其程序的內存使用情況。使用Valgrind是非常簡單的:

valgrind --leak-check=yes yourProgram arg1 arg2 

,其中Arg1和arg2的是,你的程序需要(最終)參數。

此外,使用-g標誌編譯你的程序(至少在g ++上,我不知道其他編譯器),valgrind也會告訴你至少有一行代碼發生了內存泄漏。

感謝大家的幫助!

問候
利瑪竇

+0

更重要的是,使用正確的標誌,Valgrind還可以檢測未初始化內存的使用情況,並告訴您何時/何地分配了內存。 – Novelocrat

相關問題