While debugging a program of mine, I stumbled upon a weird behaviour of the gcc compiler. I don't know what's the correct title to describe this, but take a look at the code below.
Basically, I had a function which received a void* arg
as an argument. It then casted it to a pointer of another type, HTTPRequest*
. However, I casted the wrong variable, so the code looked like
void someCallback(void* arg) {
HTTPRequest* req = (HTTPRequest*) req;
FreeRequest(req);
//re-setup request, other stuff..
}
The program then crashed within FreeRequest
with a SIGSEGV
when it tried to derefrence the pointer. Upon further inspection, req
always a had a value of NULL
.
It took me a while to realize that the cast I did was just done on the wrong variabe - it should have been
HTTPRequest* req = (HTTPRequest*) arg;
Then it all worked. I was however baffled that gcc
allowed me to not only compile this code, but throw no warning whatsoever at this line.
Consider the minimal example
#include <stdlib.h>
#include <stdio.h>
void someFunc(void* arg) {
int* a = (int*) a;
printf("a = %p\n", a);
printf("*a = %d\n", *a);
}
int main() {
int b = 42;
someFunc(&b);
return 0;
}
Compiled with
gcc -Wall -Wextra -Wpedantic -o test -O0 test.c && test.exe
Compiler outputs
test.c: In function 'someFunc':
test.c:7:9: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int *' [-Wformat=]
printf("a = %p\n", a);
^
test.c:4:21: warning: unused parameter 'arg' [-Wunused-parameter]
void someFunc(void* arg) {
^
And the program outputs:
a = 0061FFCC
*a = 6422500
With optimization at atleast O1
it outputs however:
gcc -Wall -Wextra -pedantic -o test -O1 test.c && test.exe
test.c: In function 'someFunc':
test.c:7:9: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int *' [-Wformat=]
printf("a = %p\n", a);
^
test.c:4:21: warning: unused parameter 'arg' [-Wunused-parameter]
void someFunc(void* arg) {
^
And outputs
a = 00000000
Then hangs.
So the question is: Why does gcc allow the compilation of expressions of the above form? This is obviously undefined behaviour. Then why are there no warnings about this, even with all warnings enabled?