0

I am building a project in C that basically consists in the implementation of a simplified database using a b+ tree structure. I used Xcode for coding the main file as well as 2 local libraries, and when I compile the code trough the IDE it runs perfectly.

However if I build the code using a local Makefile that I wrote myself I get a segmentation fault in a random function in the code and that it shouldn't even be reached with the arguments I gave as input.

Here it is my Makefile

CC = gcc
CFLAGS = -g -O0

all: main.exe

main.exe: main.o b_tree.o queue.o
    $(CC) $(CFLAGS) main.o b_tree.o queue.o -o main.exe

main.o: main.c b_tree.h queue.h
    $(CC) $(CFLAGS) -c main.c

b_tree.o: b_tree.h b_tree.c
    $(CC) $(CFLAGS) -c b_tree.c 

queue.o: queue.h queue.c
    $(CC) $(CFLAGS) -c queue.c 

clean:
    rm *.o main.exe

When I run using the following input arguments: ./main.exe ./my_answers/test_myanswer.txt ./testes_toy/test.txt 4 3 (output file name, input file name, tree order and size of the register to be stored in the tree), I get a segmentation fault.

I don't know it it would help but if I comment the function that sorts the children nodes it works:

void sortNodesChildren(Node *node){
    if (node->numChildren == 0) {
        return;
    }
    // Get all children nodes
    Node *childrenNodes = realloc(NULL, sizeof(node)*node->numChildren);
    for (int k = 0; k < node->numChildren; ++k) {
        Node n = getNode(node->childNodes[k]);
        childrenNodes[k] = n;
    }
    // Sort children nodes
    for(int i = 0;i<node->numChildren;i++){
        for (int j = i+1; j<node->numChildren; j++) {
            Node aux; long auxId;

            if (childrenNodes[i].registerKeys[0] > childrenNodes[j].registerKeys[0]) {
                aux = childrenNodes[i];
                auxId = node->childNodes[i];

                childrenNodes[i] = childrenNodes[j];
                node->childNodes[i] = node->childNodes[j];

                childrenNodes[j] = aux;
                node->childNodes[j] = auxId;
            }
        }
    }
    free(childrenNodes);
}

I feel like it may be something to do with the realloc function, but I have no idea what or why it works when run trough Xcode. Maybe my Makefile may be missing something.

Arthur Senna
  • 331
  • 3
  • 5
  • 1
    On POSIX system like macOS executable files doesn't need any kind of suffix or extension to make them executable. You can name your program `main` (or any other valid name in the file-system) and it would work just as well. – Some programmer dude Apr 23 '20 at 17:26
  • As for your problem I think it's time you learn how to use a debugger to catch crashes and locate where in your code they happen. – Some programmer dude Apr 23 '20 at 17:26
  • @Someprogrammerdude The .exe was just a pattern that the teacher asked for, I know it is not necessary. And I am using the Xcode debugger, but as I said it runs well on Xcode. – Arthur Senna Apr 23 '20 at 17:29
  • @DavidRanieri I saw here https://stackoverflow.com/a/16871702/9426358 how he initialized a variable of unknown length and I have been using it since. – Arthur Senna Apr 23 '20 at 17:33
  • 1
    Did you try tu run it with your debugger? Did you try valgrind? – Jabberwocky Apr 23 '20 at 17:36
  • 1
    BTW: you are aware that `realloc(NULL, sizeof(node)*node->numChildren)` is strictly the same thing as `malloc(sizeof(node)*node->numChildren)` – Jabberwocky Apr 23 '20 at 17:38
  • What happens if you comment out only the `if`part in the `sortNodesChildren`? – Jabberwocky Apr 23 '20 at 17:41
  • @Jabberwocky I am on MacOsCatalina and valgrind is not supported for it. About the realloc and malloc, I know it works the same I just choose to use realloc(NULL) so I don't have to use two different functions. – Arthur Senna Apr 23 '20 at 19:20
  • @Jabberwocky if I comment the `if` part it runs. More specifically the content inside it. But its weird cause it breaks even if the if statement returns false, and therefore it shouldn't even reach that pice of code. – Arthur Senna Apr 23 '20 at 19:23
  • 1
    Debuggers could set otherwise uninitialized memory to some specific value. For example if all memory is zeroed then an otherwise uninitialized pointer becomes equal to a null pointer. If you have a null-pointer check for an otherwise uninitialized pointer, it will seem to work when running in the debugger, but lead to undefined behavior when not running in a debugger. Or the opposite, a pointer that you think should be null might have some non-null (but invalid) value, and might seem to work fine in the debugger. – Some programmer dude Apr 24 '20 at 05:33
  • 2
    Other than that, search your code for all pointers, and make sure that they are initialized properly before you're trying to use them. And make sure you have null-pointer checks everywhere you use pointers. I also recommend that you enable a lot of extra warnings (`e.g. -Wall -Wextra -Wpedantic`) and treat them as errors, that might give some hints about possible problems. – Some programmer dude Apr 24 '20 at 05:35

1 Answers1

1

this statement:

for(int i = 0;i<node->numChildren;i++){

has to stop 1 sooner, otherwise:

for (int j = i+1; j<node->numChildren; j++) {

will be accessing beyond the end of the array

Suggest:

for( int i = 0; i < (node->numChildren - 1); i++ ){
    for ( int j = i+1; j<node->numChildren; j++ ) {

however, there are some other problems in the OPs code.

here is a proper bubble sort algorithm

void bubbleSort(int arr[], int n) 
{  
    for ( int i = 0; i < n-1; i++) 
    {      
        // Last i elements are already in place    
        for ( int j = 0; j < n-i-1; j++)
        {  
            if (arr[j] > arr[j+1]) 
            {
                swap(&arr[j], &arr[j+1]); 
            }
        }
    }
}  
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • `for (int j = i+1; jnumChildren; j++)` would not go inside the inner for loop if `i==nodo->numChildren-1` since `jnumChildren` would return false, and therefore wouldn't access beyond the array. The sorting I used was jus me being lazy and not wanting to implement a quicksort, but thanks! – Arthur Senna Apr 23 '20 at 22:45