0

I have this very simple code written in C. They are in two separate files.

myFunction.c

#include <stdlib.h>

int *extFunc() {
    int *a = (int *) calloc( 1, sizeof(int) );
    *a = 12;
    return a;
}

main.c

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

int main()
{
    int *p = (int *) extFunc();
    int x = *p; // causes segmentation fault !
    printf("%d\n", *p); // causes segmentation fault !
}

I compiled it with this command cc myFunction.c main.c and the output is like below

main.c:6:19: warning: implicit declaration of function 'extFunc' is invalid in C99 [-Wimplicit-function-declaration]
        int *p = (int *) extFunc();
                         ^
main.c:6:11: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]
        int *p = (int *) extFunc();
                 ^
2 warnings generated.

and when I run it, it gives Segmentation fault: 11. What am I doing wrong?

I checked the function when it is in the main.c file and it worked. However, I need them to be separate like above.

In my original code there are struct pointers instead of integer pointers. I explained my problem here with a simplified example.

Emad Goahri
  • 51
  • 1
  • 6
  • try int *p = malloc(sizeof(int)); and then int *p = (int *) extFunc(); – Muhammad Usman Oct 20 '16 at 08:33
  • The function is not declared neither defined for the compiler, see the error message. Never skip warnings, its a bad habit. Either you write the function in your main.c or you write a header file and include the header file in your main. – ckruczek Oct 20 '16 at 08:33
  • @jforberg the question is not about the warnings. I just added extra information of what happened when I compiled it. – Emad Goahri Oct 20 '16 at 08:37
  • @EmadGoahri Yes it is. The warnings tell you what is wrong with your code. If you had simply made a google search for "implicit declaration of function" you would have found the answer quickly. – jforberg Oct 20 '16 at 08:38
  • @jforberg ok you are right. I didn't know that. should I delete this question? – Emad Goahri Oct 20 '16 at 08:41
  • @EmadGoahri No harm done. In the future, I would encourage you to spend some more time searching the site before posting a question. Any warnings you get are probably indicative of what your problem is. – jforberg Oct 20 '16 at 08:47
  • 1
    I would recommend to add the option `-pedantic-errors` to GCC. Especially if you are a beginner still learning the language. This will give you an error and not just a warning, if you write something that isn't allowed in standard C. – Lundin Oct 20 '16 at 10:56

4 Answers4

3

You haven't provided a prototype for extFunc(). Create a header file with:

int *extFunc(void);

and include it in both source files.

Since the compiler can't see a prototype it assumed int as return type for extFunc() which probably truncates the address returned by calloc() on your system (probably 64bit system). But there's no implicit int rule since C99. Always include prototypes for functions and pay attention to compiler warnings.

P.P
  • 117,907
  • 20
  • 175
  • 238
2

The warnings are very important here. Especially the one saying

cast to 'int *' from smaller integer type 'int'

What is happening is that the compiler makes an implicit declaration of the function. One that doesn't return int * but int. On certain platform (most notably 64-bit systems) those are not the same which means the pointer p in your main function is not correct. Dereferencing it will lead to undefined behavior.

You need to add a declaration of your function for it to work:

int *extFunc(void);

int main(void) { ... }

Also note that I have changed the argument type for both your extFunc and for main. This is because in C when you don't explicitly say that a function takes void as argument then it can take any number of unspecified arguments.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Compiling both files is not enough, you need to create a header:

/* myFunction.h */

int *extFunc(); 

And then, include it in your main file:

#include <stdio.h>
#include <stdlib.h>
#include "myFunction.h" /* here */

int main()
{
   ...
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
0

The main cannot see the declaration of the function extFunc, so it's return type default to int.

As types int and int* are not of the same size, the function returns an invalid pointer, which when dereferenced caused a segmentation fault.

You will need to create a header called myFunction.h, which will contain the declaration of the function:

int* extFunc( void );

Include this header in main and also change the definition of extFunc to take no arguments in myFunction.c.

2501
  • 25,460
  • 4
  • 47
  • 87