Search code examples
cparsingdynamic-memory-allocationmidi

Parsing MIDI Files using C - (Possible Problem Allocating Memory)


I have been trying to write a MIDI parser using C.
I did my research and learned so much about the MIDI file structure from multiple sources.
Here are some of the most useful ones (for the ones that are interested):

Using information from the sources above I wrote a really unoptimised MIDI parser. The aim of the current version is to simply print what events it encountered and save them on a file.
I have managed to parse through midi files [though I encountered a meta event that shouldn't exist (meta event 0x09)].


However, while implementing the save function I have seen that some midi files I had causes problems if I try to save them (Just parsing them works fine)(The program freezes for a while and returns non-zero value before finishing execution).
I think the problem could be associated with either the way I am allocating the memory or accessing it.
Here's the code (As I said, it's not pretty yet)):

_MtrkCD **MtrkDatas = (_MtrkCD **)(malloc(sizeof(_MtrkCD *)));
uint64_t i,j,k,p;
for (p=0;p<MthdData->tracks_count;p++){
    MtrkDatas[p] = (_MtrkCD *)(malloc(sizeof(_MtrkCD)));
    if(!_ReadMtrkChunk(midiFile,MtrkDatas[p],p,print)){
        printf("Error reading MTrk Chunk. Bad MTrk.\n");
        return 0;
    }
}

^the part that allocates memory (posted because it's required)^

main.c
Here are the two example files I used(one works fine, the other causes problems):
home.mid(This file doesn't cause problems)
014-Theme03.mid(This is the one causing problems)
Here are the outputs when I run the program:
home Parsed.txt(Expected Output)
014-Theme03 Parsed.txt(What even is this?)
Again, I want to point out to some things that I have noticed:

  1. The program parses both MIDI files without any problems
  2. The program not only fails to write event output to .txt files, but also fails to write the correct amount of bytes

Thank you all for your time. (Also I would be grateful if someone formatted the text better. I'm not very good at that as you can see.)

Update:

Here's the working code. I made a very simple mistake allocating memory for tracks. Thanks to Paul R for pointing out the mistake.

_MtrkCD **MtrkDatas = (malloc(sizeof(_MtrkCD *) * (MthdData->tracks_count)));
uint64_t i,j,k,p;
for (p=0;p<MthdData->tracks_count;p++){
    MtrkDatas[p] = (malloc(sizeof(_MtrkCD)));
    if(!_ReadMtrkChunk(midiFile,MtrkDatas[p],p,print)){
        printf("Error reading MTrk Chunk. Bad MTrk.\n");
        return 0;
    }
}

Solution

  • In this line:

    _MtrkCD **MtrkDatas = (_MtrkCD **)(malloc(sizeof(_MtrkCD *)));
    

    you are only allocating an array of one pointer. So here you have undefined behaviour:

    MtrkDatas[p] = (_MtrkCD *)(malloc(sizeof(_MtrkCD)));
    

    whenever p > 0 (i.e. if tracks_count > 1 then you are in trouble).

    You should probably change:

    _MtrkCD **MtrkDatas = (_MtrkCD **)(malloc(sizeof(_MtrkCD *)));
    

    to:

    _MtrkCD **MtrkDatas = malloc(MthdData->tracks_count * sizeof(_MtrkCD *));
    

    (note that the cast has been removed as it's redundant and potentially dangerous to cast the result of malloc and friends in C).