0

I am trying to create a library for college that handles musical partitions from XML files. I don't want to get into much detail, but I have a function that creates the partition score and another that adds individual notes score_add_note.

The prototypes are as follows :

score_t* score(size_t tempo, size_t duration, size_t sig, size_t nbInstr)
void score_add_note(score_t* sc, size_t ins, size_t bar, pitch_t p, size_t start, size_t duration)

I have also transformed the XML file into a structure that I have made, it is called e in this case.

In one occasion, I used these functions like this :

score_t* sc = score(atoi(e->at_head->value), atoi(e->at_head->next->value), atoi(e->at_head->next->next->value), atoi(e->at_head->next->next->next->value));
score_add_note(sc, 0, 0, 60, 0, 6);

The attributes are part of the XML structure.

This doesn't work, the score_add_note function never stops executing.

However, if I print the values from the attributes to the score function beforehand, it works correctly:

printf("%d\n", atoi(e->at_head->value));
printf("%d\n", atoi(e->at_head->next->value));
printf("%d\n", atoi(e->at_head->next->next->value));
printf("%d\n", atoi(e->at_head->next->next->next->value));

score_t* sc = score(atoi(e->at_head->value), atoi(e->at_head->next->value), atoi(e->at_head->next->next->value), atoi(e->at_head->next->next->next->value));
score_add_note(sc, 0, 0, 60, 0, 6);

Am I making some mistake or is this a bug in C. If so, is there any way around it? Btw, I am using gcc as my compiler.

EDIT: As asked, here is the score_add_note function

void score_add_note(score_t* sc, size_t ins, size_t bar, pitch_t p, size_t start, size_t duration){
    if(sc->system[ins].tab[bar] == NULL){
        sc->system[ins].tab[bar] = (bar_t*) malloc (sizeof(bar_t));
        sc->system[ins].tab[bar]->start = start;
        sc->system[ins].tab[bar]->duration = duration;
        sc->system[ins].tab[bar]->pitch = p;
    }else{
        note_t* note = sc->system[ins].tab[bar];
        while(1){
            if(note->next == NULL){
                note->next = (note_t*) malloc (sizeof(note_t));
                note = note->next;
                break;
            } 
            note = note->next;
        }
        note->start = start;
        note->duration = duration;
        note->pitch = p;
    } 
}

There is a chance that the function is stuck in an infinite loop, but the arguments are the same in both cases.

This is the score function:

score_t* score(size_t tempo, size_t duration, size_t sig, size_t nbInstr){
    score_t* sc = (score_t*) malloc (sizeof(score_t));
    sc->tempo = tempo / 60;
    sc->duration = duration;
    sc-> time_sig = sig;
    sc->sys_size = nbInstr;
    sc->system = (staff_t*) malloc (nbInstr * sizeof(staff_t));
    for(int i = 0; i < nbInstr; i++){
        sc->system[i].tab = (bar_t**) malloc (duration * sizeof(bar_t*));
    }
    return sc;
}

These are the types I have created:

typedef struct note_s{
    size_t start;
    size_t duration;
    pitch_t pitch;
    struct note_s* next;
}note_t;


typedef note_t bar_t;

typedef struct staff_s{
    bar_t** tab;
}staff_t;


struct score_s{
    size_t tempo;
    size_t duration;
    size_t time_sig;
    size_t sys_size;
    staff_t* system;
};
  • How can anybody determine why "`score_add_note` function never stops executing" if you don't show the definition? – Fiddling Bits Jan 08 '20 at 13:55
  • There isn't a problem with that function. In both cases, that function receives the same attributes. In any case I'll post the function. – asbestos_moccasin Jan 08 '20 at 13:57
  • 2
    @asbestos_moccasin There’s either a problem with that function, or with the surrounding code. Since the behaviour differs based on seemingly unrelated changes, there’s a high (>99%) chance that your code invokes undefined behaviour. By contrast, the chance of a compiler bug is <0.1%. – Konrad Rudolph Jan 08 '20 at 13:58
  • 1
    _I don't want to get into much detail_, That's okay, but you have to put in at least as much detail as is needed to address your questions. If possible, prepare a very small example of code that contains only enough to illustrate the issue you are seeing and edit your post with that example. ( [mcve] ) – ryyker Jan 08 '20 at 13:58
  • On a side note, please don't use the `_t` suffix for your types. It is a reserved suffix for the C implementations to add new types. – darnir Jan 08 '20 at 14:05
  • 2
    You don't terminate your list. You never assign `NULL` to `note->next;` (for the newly created note) during adding a node. Probably your `score()` function contains the same bug. But as you don't show us the mandatory MCVE but only some incomplete snippets, we cannot be sure what's wrong. – Gerhardh Jan 08 '20 at 14:08
  • 2
    @darnir *On a side note, please don't use the _t suffix for your types. It is a reserved suffix for the C implementations to add new types* Not in C11: [**7.1.3 Reserved identifiers**](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) – Andrew Henle Jan 08 '20 at 14:08
  • I have also added the `score` function. – asbestos_moccasin Jan 08 '20 at 14:16
  • @AndrewHenle: But Section 7.31.10 (Future Directions) essentially reserves the right to add new typedefs to `stdint.h` with the `_t` suffix, which means you should steer clear of it. Not to mention, it is also prohibited in the GNU Lib C Manual: https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html And is a reserved suffix according to the POSIX specification as well – darnir Jan 08 '20 at 14:22
  • 2
    @darnir That's only [limited to `[u]int*_t`](https://port70.net/~nsz/c/c11/n1570.html#7.31.10). – Andrew Henle Jan 08 '20 at 14:26
  • @AndrewHenle Do you have a link that my browser won't flag as a "potential security threat"? It's Firefox, and apparently, "Most browsers no longer trust certificates issued by GeoTrust [_et al._]". However, yeah, `_t` is not reserved for the implementation in C, only by POSIX, which many people can go their entire lives without ever using. – underscore_d Jan 08 '20 at 14:38
  • 1
    @underscore_d That's the only marked-up HTML version that I'm aware of. See [**Where do I find the current C or C++ standard documents?**](https://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents) for PDFs or plain text. – Andrew Henle Jan 08 '20 at 14:44
  • As I guessed, your `score` function has the same problem. You do not initialize any of the pointers in the array you allocate: `sc->system[i].tab = (bar_t**) malloc (duration * sizeof(bar_t*));` You have `duration` pointers that are not initialized to `NULL`. – Gerhardh Jan 08 '20 at 17:12
  • BTW: you do not show definition of `score_t`. Please do not expect that we hunt for all the missing information. There is a reason why you shall provide a [MCVE](https://stackoverflow.com/help/mcve) It is to ensure that everything is there. – Gerhardh Jan 08 '20 at 17:19

1 Answers1

4

This code

    note_t* note = sc->system[ins].tab[bar];
    while(1){
        if(note->next == NULL){
            note->next = (note_t*) malloc (sizeof(note_t));
            note = note->next;
            break;
        } 
        note = note->next;
    }

never sets note->next to NULL when creating a new node on the linked list. You therefore invoke undefined behavior when accessing the list later.

This would be better:

    note_t* note = sc->system[ins].tab[bar];
    while (1) {
        if (note->next == NULL){
            note->next = malloc(sizeof *note->next);
            note = note->next;
            note->next = NULL;
            break;
        } 
        note = note->next;
    }
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • Thanks, but this doesn't seem to be the problem. – asbestos_moccasin Jan 08 '20 at 14:17
  • 1
    This is also the case for `sc->system[ins].tab[bar] = (bar_t*) malloc (sizeof(bar_t));` where `next` is neither set to null. – Paul Ogilvie Jan 08 '20 at 14:18
  • I've corrected that too but it isn't the problem either. – asbestos_moccasin Jan 08 '20 at 14:20
  • 1
    @asbestos_moccasin There are likely problems in the code you didn't post, then. If you're on Linux, try [using Valgrind](https://stackoverflow.com/questions/5134891/how-do-i-use-valgrind-to-find-memory-leaks) to find memory access problems. – Andrew Henle Jan 08 '20 at 14:36
  • @asbestos_moccasin I have already mentioned in my first comment that you probable have similar problem in your `score` function. Did you fix that, too? – Gerhardh Jan 08 '20 at 17:25