Search code examples
csortingdynamic-memory-allocation

sorting crashes with address boundary error in C


this is minimum reproducible example of my problem. I've got struct with some data in it, which I need to sort in the lexicographic order. But when I run the sort() function it crashes. I think the problem might be the way I allocate/reallocate memory, but didn't figure out what exactly it is.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int num_id = 5;
typedef struct data_id
{
    char *id;
    int marker;
} data_id;
data_id *buffer_sort, *nodeList;

void sort()
{
    buffer_sort = malloc(sizeof(nodeList)*100);
    for (int i = 0; i < num_id; ++i)
    {
        for (int j = i + 1; j < num_id; ++j)
        {
            // swapping strings if they are not in the lexicographical order
            if (strcmp(nodeList[i].id, nodeList[j].id) > 0)
            {
                strcpy(buffer_sort[i].id, nodeList[i].id);
                buffer_sort[i].marker = nodeList[i].marker;

                strcpy(nodeList[i].id, nodeList[j].id);
                nodeList[i].marker = nodeList[j].marker;

                strcpy(nodeList[j].id, buffer_sort[i].id);
                nodeList[j].marker = buffer_sort[i].marker;
            }
        }
    }
    free(buffer_sort);
}

void fill(){
    nodeList = malloc(sizeof *nodeList*5);

    nodeList[0].id = "a";
    nodeList[1].id = "e";
    nodeList[2].id = "c";
    nodeList[3].id = "b33";
    nodeList[4].id = "cc";
    nodeList[0].marker = 0;
    nodeList[1].marker = 255;
    nodeList[2].marker = 0;
    nodeList[3].marker = 2;
    nodeList[4].marker = 0;
}

int main(){
    fill();
    sort();
    
    for (int i = 0; i<num_id; ++i){
        printf("Marker:%d\n", nodeList[i].marker);
        printf("ID:%s\n\n", nodeList[i].id);
    }
}

Solution

  • Swapping strings looks suspicious. strcpy(buffer_sort[i].id, nodeList[i].id) attempts to copy into an uninitialized .id, which is undefined behavior.

    Use a simply struct exchange.

    // strcpy(buffer_sort[i].id, nodeList[i].id);
    // buffer_sort[i].marker = nodeList[i].marker;
    // strcpy(nodeList[i].id, nodeList[j].id);
    // nodeList[i].marker = nodeList[j].marker;
    // strcpy(nodeList[j].id, buffer_sort[i].id);
    // nodeList[j].marker = buffer_sort[i].marker;
    
    // Swap the struct
    data_id tmp = nodeList[i];
    nodeList[i] = nodeList[j];
    nodeList[j] = tmp;
    

    Use buffer_sort = malloc(sizeof(nodeList)*100); --> buffer_sort = malloc(sizeof *buffer_sort * 100); to avoid mis-sizing.

    sizeof(nodeList) is the size of a pointer. sizeof *buffer_sort is the size of one object buffer_sort points to.

    IAC, buffer_sort not needed.


    Other problems may exist.