Reputation: 1210
I have code in C (linux(x86_64)) some like this:
typedef struct
{
char k[32];
int v;
}ABC;
ABC states[6] = {0};
ABC* get_abc()
{
return &states[5];
}
while in main():
int main()
{
ABC *p = get_abc();
.
.
.
printf("%d\n", p->v);
}
I am getting segmentation fault at printf statement while accessing p->v. I tried to debug it from gdb and it says "can not access the memory". One important thing here is that when I compile this code, gcc throws me a warning on ABC *p = get_abc(); that I am trying to convert pointer from integer. My question here is that I am returning address of structure from get_abc() then why compiler gives me such warning? why compiler considers it as integer? I think I am getting segmentation fault due to this warning as an integer can not hold memory address in x86_64.
Any help would be appreciated.
Upvotes: 2
Views: 1308
Reputation: 13414
Define the get_abc
prototype before main
function. If function prototype is not available before that function call means, compiler will treat that function by default as passing int
arguments and returning int
. Here get_abc
actually returning 8 byte address, but that value has been suppressed to 4 bytes and it is stored in ABC *p
variable which leads the crash.
ABC* get_abc();
int main()
{
ABC *p = get_abc();
}
Note : This crash will not occur in 32 bit machine where size of int and size of address is 4 bytes, because suppression will not happen. But that warning will be there.
Upvotes: 5
Reputation: 263177
You haven't shown us all your code, but I can guess with some confidence that the get_abc()
and main()
functions are defined in separate source files, and that there's no visible declaration of get_abc()
visible from the call in main()
.
You should create a header file that contains a declaration of get_abc()
:
ABC *get_abc();
and #include
that header both in the file that defines get_abc()
and in the one that defines main()
. (You'll also need header guards.) You'll need to move the definition of the type ABC
to that header.
Or, as a quick-and-dirty workaround, you can add an explicit declaration before your definition of main()
-- but that's a rather brittle solution, since it depends on you to get the declaration exactly right.
In the absence of a visible declaration, and undeclared function is assumed to return int
. The compiler sees your call to get_abc()
, generates code to call it as if it returned an int
, and implicitly converts that int
value to a pointer. Hilarity ensues.
Note: There actually is no implicit conversion from int
to pointer types, apart from the special case of a null pointer constant, but many compilers implement such an implicit conversion for historical reasons. Also, the "implicit int
" rule was dropped in the 1999 version of the standard, but again, many compilers still implement it for historical reasons. Your compiler should have options to enable better warnings. If you're using gcc, try gcc -pedantic -std=c99 -Wall -Wextra
.
Upvotes: 2