Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error apparently raised by not yet executed code

I'm learning c++ by writing a program to convert MIDI files to Lilypond source files. My program is composed by two main parts:

  • a MIDI file parser, that creates an object called MidiFile.
  • a converter that takes a MidiFile objects and converts it to a Lilypond source.

Today I've started coding the converter, and while I was testing it a strange error occurred: the program dies after an exception being thrown, more specifically a HeaderError, that means that the header chunk in the MIDI file is not as expected. It wouldn't seem that strange, but this error shows up only if I add a line of code after the buggy code! I add the main() function to better explain myself

#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;
}

With my main() like this, everything works properly, but, if I add something between buildMidiFile and the while loop, the function buildMidiFile throws the exception!!! Even if it's a completely unrelated instruction!

#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;
}

I can't explain myself how this is possible. So if anyone has ideas or advices, all the help would be greatly appreciated :) If it's helpful I can post the source code for other classes and/or functions.

like image 636
Matteo Ceccarello Avatar asked Jul 04 '11 14:07

Matteo Ceccarello


1 Answers

Solved! As pointed out in comments to the question, it was a problem caused by some sort of memory corruption. As suggested I used a memory checher (valgrind) and found out that it was a really stupid error: i simply forgot to initialize a variable in a for loop, something like

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

and this led to that strange error :-) Initializing i to 0 solved the problem, and now the program works with Parser object placed either on the stack or on the heap.

So I suggest others incurring in similar problems to use a memory checker to control the memory usage of their program. Using valgrind is really simple:

valgrind --leak-check=yes yourProgram arg1 arg2

where arg1 and arg2 are the (eventual) arguments that your program requires.

Furthermore compiling your program with the -g flag (at least on g++, I don't know on other compilers), valgrind will also tell you at wich line of code the memory leak occurred.

Thanks to everybody for the help!

Regards
Matteo

like image 195
Matteo Ceccarello Avatar answered Sep 20 '22 02:09

Matteo Ceccarello