Reputation: 501
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
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
Reputation: 181179
I figured out the solution which was adding
l1 -> next = NULL;
in thenewList
function andl2 -> next = NULL;
in theappendList
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
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