AppTest
AppTest

Reputation: 501

Null pointer detection in tcc

I created a very simple linked list and noticed a difference in output for tcc filename.c vs tcc filename.c -run for my code:

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

struct llist {
    struct llist *next;
    struct llist *last;
    struct llist *first;
    int value;
    int item;
    int *length;
};

struct llist *newList(int v){

    struct llist *l1 = malloc(sizeof(struct llist)); 
    l1 -> length = malloc(sizeof(int));
    *l1 -> length = 1;

    l1 -> value = v;    
    l1 -> item = 0;    
    l1 -> first = l1;

    return l1;
}

struct llist *appendList(struct llist *l1, int v){

    struct llist *l2 = malloc(sizeof(struct llist));

    l2 -> value = v;
    l2 -> last = l1;
    l2 -> first = l1 -> first;
    l2 -> length = l1 -> length; 
    *l2 -> length += 1; 
    l2 -> item = l1 -> item + 1;

    l1 -> next = l2;

    return l2;    
};

int main(){
    struct llist *list = newList(4);
    list = appendList(list, 6);
    list = appendList(list, 8);
    list = appendList(list, 10);

    list = list -> first;

    int end = 0;
    while(end==0){

        printf("VAL: %d\n", list -> value);

        if(list -> next == NULL){
            printf("END\n");
            end = 1;
        }else{

            list = list -> next;
        }
    }


    return 0;
}

For compiling with tcc filename.c and then running it produces the output I expected:

VAL: 4
VAL: 6
VAL: 8
VAL: 10
END

It's also the output I get in GCC and clang.

When I use tcc filename.c -run I get:

VAL: 4
VAL: 6
VAL: 8
VAL: 10
VAL: 27092544
VAL: 1489483720
VAL: 0
END

With the last number always being zero and the other two extra values being different every time I run.

I figured out the solution which was adding l1 -> next = NULL; in the newList function and l2 -> next = NULL; in the appendList function.

But I was wondering why there was a difference in output. Is there a bug in the compiler or was I wrong for not initialising the pointer to NULL even though it works in most compilers?

Upvotes: 0

Views: 139

Answers (3)

supercat
supercat

Reputation: 81247

The function calloc() returns a pointer to a sequence of bytes that are initialized to zero; malloc(), by comparison, returns a pointer to a sequence of bytes that may or may not happen to initially contain zero. On some platforms, those bytes will always contain zero after a malloc(); on others, at least some of them never will. Generally, it's unpredictable which bytes will hold zero and which won't.

On most platforms, including nearly all that have been created in the last couple decades, clearing all of the bytes of a pointer object will set the pointer to NULL. On platforms that document such behavior, using "calloc" rather than "malloc" to create space for a structure containing pointers would be a reliable way of initializing to NULL all pointers therein. If one creates storage with "malloc" or "realloc" rather than "calloc", however, it will be necessary to either use "memset" to set all the bytes to zero, or else expressly set pointers contained therein to NULL.

Upvotes: 0

John Bollinger
John Bollinger

Reputation: 181179

I figured out the solution which was adding l1 -> next = NULL; in the newList function and l2 -> next = NULL; in the appendList function.

But I was wondering why there was a difference in output. Is there a bug in the compiler or was I wrong for not initialising the pointer to NULL even though it works in most compilers?

You were wrong to access the pointer's value without having assigned it one or caused it to be explicitly or implicitly initialized (which are different from assigning a value). Doing so produces undefined behavior. That the program nevertheless happened to exhibit the behavior you expected under some circumstances is a possible and plausible result, but it does not validate the program.

Moreover, you are likely to find that your original approach does not work reliably with the other compilers you tested under more complex circumstances (but I can make only a probabilistic statement about that, because "undefined").

Upvotes: 1

Mquinteiro
Mquinteiro

Reputation: 1080

Normally when you debug a program the debugger initialize everything, but in production there is no initialization, so next values is not null

Initialize next variables.

Upvotes: 0

Related Questions