#1
  1. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95

    undefined reference using a global variable in a function


    The answer to this is probably simple, but im not used to programming in C using gcc. Here is the error :

    In function `print_statistics':
    /home/1nfamus/Programs/hping2-rc2/statistics.c:42: undefined reference to `averageID'
    relid.o: In function `relativize_id':
    /home/1nfamus/Programs/hping2-rc2/relid.c:43: undefined reference to `averageID'collect2: ld returned 1 exit status
    make: *** [hping2] Error 1


    averageID is a globabl variable i declared in the "global.h" included in both of the above .c files. What exactly does undefined reference mean?
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    ld is the GNU linker. averageID is declared in global.h, but in which .c source file is it actually defined?
  4. #3
  5. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    edit: ahh nevermind; i didnt realize i had to initialize averageID in main. got my revamped hping working perfect now!
    Last edited by infamous41md; May 5th, 2003 at 12:21 PM.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    Those are just references. Where is it defined?
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222

    Tested it ...


    When in doubt, code and test it, I always say.

    Since I always declare a global variable as an extern in a header file, I assumed that either you had done so as well or, if not, that gcc had assumed it to be an extern. To verify what would happen if the extern keyword were left out of the header, I did a quick two-module test project:

    mod1.c
    Code:
    // module 1
    
    #include "global.h"
    
    //int g_int = 0;
    
    int main(void)
    {
        g_int = 42;
        fn1();
        return 0;
    }
    mod2.c
    Code:
    // module 2
    
    #include <stdio.h>
    #include "global.h"
    
    
    void fn1(void)
    {
        printf("g_int = %d\n",g_int);
    }
    global.h
    Code:
    #ifndef _GLOBAL_H_
    #define _GLOBAL_H_
    
    int g_int;
    
    void fn1(void);
    
    #endif
    Command Line:
    Code:
    C:\dcw\PROJECTS\TEST>gcc mod1.c mod2.c
    
    C:\dcw\PROJECTS\TEST>a
    g_int = 42
    
    C:\dcw\PROJECTS\TEST>
    Normally, I would have expected to get a link error for multiple definitions of the same variable, so I was surprised by the apparently clean make.

    Then I expected each module to have its own copy of g_int so that the change in mod1 would not be seen by mod2. Again I was wrong. I just ran nm on a.exe and there is only one instance of g_int.

    Personally, I find gcc to be a bit too accommodating here. Of course, it might just be that my gcc is configured to be less strict than I think it should be (I haven't changed it, so it's set to the installed default -- MinGW installed by Dev-C++ beta 5).
    Last edited by dwise1_aol; May 5th, 2003 at 01:54 PM.
  10. #6
  11. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    yes i declared it as an extern int in the globals file.
    so when u assigned it in main() that was taken to be the "defining" of it?
    ... this stuff is kind of confusing to me, i've never used the extern keyword before, i had to look it up to even know what it meant. this was the C source for hping2. i was trying to modify a couple things in it, and i came to realize how different C is compared to C++. the format and flow of the program is so hard for me to understand. i learned how to do pretty much everything from an object oriented perspective so following along in these progs is :confused: . i want to rewrite it into an oo version:D
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    Originally posted by infamous41md
    so when u assigned it in main() that was taken to be the "defining" of it?
    No, the definition in my test (not using "extern") was when the header file got included. What the #include directive does is to insert the file directly into the source file at that point. You could also use it to insert executable code into the source file -- rarely used for that, but it can be done.

    More properly, mod1.c and global.h should have read:
    Code:
    #ifndef _GLOBAL_H_
    #define _GLOBAL_H_
    
    extern int g_int;  /* just declared here; no memory space allocated for it yet */
    
    void fn1(void);
    
    #endif
    
    --------------------------
    
    // module 1
    
    #include "global.h"
    
    int g_int = 0;  /* now this is where it actually gets defined  */
    
    int main(void)
    {
        g_int = 42;
        fn1();
        return 0;
    }
    Originally posted by infamous41md
    i was trying to modify a couple things in it, and i came to realize how different C is compared to C++. the format and flow of the program is so hard for me to understand. i learned how to do pretty much everything from an object oriented perspective so following along in these progs is :confused: . i want to rewrite it into an oo version:D
    C is not really that different from C++ except for the overall approach that OOP offers. I remember that one of the major hurdles for C programmers to get over was switching over to an OO approach. Similarly, I saw some programmers really struggle learning the Windows approach of doing everything inside of event handlers. Encountering a different way of doing something is rarely easy.

    However, extern is also needed in C++ when you define a global object in one module that is needed in another module. Though you probably have not encountered it because a common practice is to access such objects through pointers that are passed and returned through functions and methods.
  14. #8
  15. No Profile Picture
    Offensive Member
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2002
    Location
    in the perfect world
    Posts
    622
    Rep Power
    27
    Ummm.......

    I think you have it the wrong way round. I think you are just creating two variables with the same name. Try using g_int in another file that does not include global.h

    Try this method

    globals.h (include this header file ONLY in the main file of your app)
    In this example the main app file is
    main.c


    globals.h
    Code:
    #ifndef _GLOBAL_H_//beware of using variables and defines with leading underscores as this is not ANSI compliant (they are reserved)
    #define _GLOBAL_H_
    
    int g_int=0;  //declare and init here
    
    void fn1(void);
    
    #endif
    in the main.c
    Code:
    #include   globals.h
    
    extern int     g_int;//can not init here
    in any other file in the project just declare it as

    extern int g_int;//can not be init here
    The essence of Christianity is told us in the Garden of Eden history. The fruit that was forbidden was on the Tree of Knowledge. The subtext is, All the suffering you have is because you wanted to find out what was going on. You could be in the Garden of Eden if you had just kept your f***ing mouth shut and hadn't asked any questions.

    Frank Zappa
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    That's backwards. dwise had it right. You want the header file to be included anywhere that something in it is needed. The definition should only be in the module that owns the item.
  18. #10
  19. No Profile Picture
    Offensive Member
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2002
    Location
    in the perfect world
    Posts
    622
    Rep Power
    27
    dwise1_aol uses the 'common' method of using extern. This is not allowed under ANSI C. A stricter declaration is required (as per my example). Both will work however.

    But why declare the global (g_int) in a header and then again in a file that includes the globals header?
    (Comment out the #include and see if you can still use g_int, if so why use that method?)

    I like to declare any global variables in one header file and externally define _only_ those I need in any source file in the project (and not have to include them all as per dwise1_aol's method).
    The essence of Christianity is told us in the Garden of Eden history. The fruit that was forbidden was on the Tree of Knowledge. The subtext is, All the suffering you have is because you wanted to find out what was going on. You could be in the Garden of Eden if you had just kept your f***ing mouth shut and hadn't asked any questions.

    Frank Zappa
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    No, dwise's method is correct. Your method is doing effectively the same thing, but it isn't as clear nor as standard. In dwise's example, he is defining the variable once in the .c file. He is then providing a way for other files to include its declaration. Your method also defines the variable once, and provides a way to include its declaration. For this simple example both methods are equivalent. Where I believe your method becomes unmanageable is when there is a need to declare structures, types, functions, and even #defines. With your method you would have to put each of these into every file that needs to use them, including the one that "owns" them. In dwise's method, they would just be in the .h file and each file would just need to include that file. In general, I feel it is typically best to not include definitions in header files.
  22. #12
  23. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    Just to clarify what I did, I tried an experiment in which I defined a global variable in the header just to see if I could duplicate what infamous was seeing.

    I don't normally do that. Normally, I have a header for each code module which contains only:
    1. #defines that are needed by any other modules in the program.
    2. type definitions that will be needed by other modules.
    3. extern variable declarations that will be needed by other modules.
    4. function prototypes that will be needed by other modules.

    Normally, I never put a variable definition in a header file and I never put code in a header file (notable exception: an inline function in a class). And if something is not needed outside of the module, it doesn't go into the header file.

    Rather than collect the all the type definitions or the externs of all the global variables into a single header, I will usually place them in the header for the module that defines them. That way, a module can be more selective about what it pulls in.
    Last edited by dwise1_aol; May 8th, 2003 at 10:09 AM.
  24. #13
  25. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    That is exactly what I was talking about doing. Everything that another module needs to know about the module of interest should be in the header. Perhaps I should have been more clear that I was referring to the post where dwise1_aol said

    More properly, mod1.c and global.h should have read:

    Code:
    #ifndef _GLOBAL_H_
    #define _GLOBAL_H_
    
    extern int g_int;  /* just declared here; no memory space allocated for it yet */
    
    void fn1(void);
    
    #endif
    
    --------------------------
    
    // module 1
    
    #include "global.h"
    
    int g_int = 0;  /* now this is where it actually gets defined  */
    
    int main(void)
    {
        g_int = 42;
        fn1();
        return 0;
    }
  26. #14
  27. No Profile Picture
    Offensive Member
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2002
    Location
    in the perfect world
    Posts
    622
    Rep Power
    27
    I keep all structs in one header, all defines in another, all prototypes in another and all of these includes in single file (as well as the standard headers).
    Then all I have to is include a single file.

    I do not like to use globals and if I do I want only the ones I specifically allow (to be seen by a particular file). Otherwise dual use of a variable name can result.

    It is what is clearer to you and the next guy who has to read the code (and work out where the variable is defined) but some are not considered correct as per ANSI

    ie void main() is not standard but will work.

    As to the ANSI C standard of extern definitions

    http://www.lysator.liu.se/c/rat/c1.html#3-1-2-2
    The essence of Christianity is told us in the Garden of Eden history. The fruit that was forbidden was on the Tree of Knowledge. The subtext is, All the suffering you have is because you wanted to find out what was going on. You could be in the Garden of Eden if you had just kept your f***ing mouth shut and hadn't asked any questions.

    Frank Zappa
  28. #15
  29. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    According to the link you provided, both of the methods we have discussed are correct. As you point out, it is more a matter of style as to which should be used.

IMN logo majestic logo threadwatch logo seochat tools logo