Thread: Undefined symbol when moving (unrelated) variable from source to header

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    6

    Undefined symbol when moving (unrelated) variable from source to header

    Hello! As the title suggests I'm getting an undefined symbol error from the linker when I try to compile something I coded. I won't paste it all, but I'll try to show you what I believe are the most relevant pieces. So I have
    menus.h
    Code:
    typedef struct menuOps {
    	int num;
    	char *string[MAXOPS];
    } menuOPS;
    ...
    menuOPS op_splash = {4, { "string1" , "string2" , "string3" , "string4" } };
    
    void menu_splash();
    void menu(void (*menufunc)(void), menuOPS ops);
    menus.c
    Code:
    #include "menus.h"
    
    void menu(void (*menufunc)(void), menuOPS ops) {
    ...
    }
    
    void menu_splash() {
    ...
    }
    interface.h
    Code:
    #include <...>
                    ...
    int splash();
    int parseOp();
    interface.c
    Code:
    #include "interface.h"
    #include "menus.h"
    
    int splash() {
    ...
    menu(&menu_splash,op_splash);
    ...
    }
    int main() { ... }
    When compiling interface.c I get this error:
    Code:
    Undefined symbols:
      "_menu_splash", referenced from:
          _menu_splash$non_lazy_ptr in ccGrWt8C.o
      "_menu", referenced from:
          _splash in ccGrWt8C.o
    ld: symbol(s) not found
    I've been around this for hours, mostly because I can't understand the following:
    If I move the op_splash declaration (line in red) inside menus.c then I don't get this error (Actually I get another one about op_splash not being declared, which is understandable). Does anyone have an idea about what I'm doing wrong?

    Thanks

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Code:
    /* menus.h */
    ...
    menuOPS op_splash = {4, { "string1" , "string2" , "string3" , "string4" } };
    ...
    You generally should NOT do this (declare a variable) in a header. If you do, you will potentially create multiple copies of the same variable (one in each .c file that includes menus.h in this case)

    I'm not sure you showed enough of the code to generate the error you are seeing. Why not create the minimum set of files that does and provide these? Don't make us guess.
    Last edited by mike65535; 04-18-2011 at 11:55 AM.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Some of this might not matter, but since I don't have your full source code, here are a few notes on using .h files and multiple source files:
    • Always use include guards in your header files. This prevents multiple definition errors.
    • Never define a variable (or a function) in a header file. Only define types, and declare variables and functions (prototypes) as extern.
    • The order you specify files on the command line for compiling may make a difference in linking depending on the compiler you use.


    As it is, you should have op_splash defined in menus.c and only declared in menus.h, like so:

    menus.h
    Code:
    #ifndef menus_h__  // dig these include guards!
    #define menus_h__
    
    typedef struct menuOps {
            int num;
                char *string[MAXOPS];
    } menuOPS;
    ...
    extern menuOPS op_splash;  // just notify the compiler it exists somewhere, the linker will find it later
    
    void menu_splash();
    void menu(void (*menufunc)(void), menuOPS ops);
    
    #endif  // menus_h__
    menus.c
    Code:
    #include "menus.h"
    
    menuOPS op_splash = {4, { "string1" , "string2" , "string3" , "string4" } };
    
    void menu(void (*menufunc)(void), menuOPS ops) {
    ...
    }
    
    void menu_splash() {
    ...
    }

  4. #4
    Registered User
    Join Date
    Apr 2011
    Posts
    6
    Thanks for the reply anduril462! Indeed I dug those include guards The problem is, after making the changes you suggested, I just got an increased number of undefined symbols:
    Code:
    Undefined symbols:
      "_menu_splash", referenced from:
          _menu_splash$non_lazy_ptr in ccU7Jy7b.o
      "_op_splash", referenced from:
          _op_splash$non_lazy_ptr in ccU7Jy7b.o
      "_menu", referenced from:
          _splash in ccU7Jy7b.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status
    What the..? I just don't get it =/

    The strange thing is, if I don't declare the
    Code:
    extern menuOPS op_splash;
    in menus.h he doesn't complain about any undefined symbols! everything looks right except for the fact that he can't find op_splash which is used in interface.c (obviously).. I put the declaration in the header file, the linker complains about undefined symbols. I don't, and he can't find op_splash's declaration. Running out of ideas here
    Last edited by k16; 04-18-2011 at 12:24 PM.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    In menus.h, would it help if you put:
    Code:
    extern void menu_splash();
    extern void menu(void (*menufunc)(void), menuOPS ops);

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Seems to me there's something missing in the code you are supplying. Can you not create a minimum set of files to exhibit the problem and let us look at it? As I said, don't make us guess.

  7. #7
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Quote Originally Posted by nonoob View Post
    In menus.h, would it help if you put:
    Code:
    extern void menu_splash();
    extern void menu(void (*menufunc)(void), menuOPS ops);
    Does one really need extern for function prototypes? I know we (almost) all use them.

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Okay, as proof of concept, here is a very simple version of your code with the ...s filled in just enough to get it to compile and do something:

    menus.h
    Code:
    #ifndef menus_h__
    #define menus_h__
    
    #define MAXOPS 5
    
    typedef struct menuOps
    {
            int num;
            char *string[MAXOPS];
    } menuOPS;
    
    extern menuOPS op_splash;
    
    extern void menu_splash();
    extern void menu(void (*menufunc)(void), menuOPS ops);
    
    #endif  // menus_h__
    menus.c
    Code:
    #include <stdio.h>
    
    #include "menus.h"
    
    menuOPS op_splash = {4, { "string1" , "string2" , "string3" , "string4" } };
    
    void menu(void (*menufunc)(void), menuOPS ops) {
        puts(__func__);
    }
    
    void menu_splash() {
        puts(__func__);
    }
    interface.h
    Code:
    #ifndef interface_h__
    #define interface_h__
    
    extern int splash();
    extern int parseOp();
    
    #endif  // interface_h__
    interface.c
    Code:
    #include <stdio.h>
    
    #include "interface.h"
    #include "menus.h"
    
    int splash()
    {
        puts(__func__);
        menu(&menu_splash,op_splash);
        return 42;
    }
    
    int main()
    {
        printf("Result of splash is: %d\n", splash());
        return 0;
    }
    I can compile this fine, no errors or warnings, using "gcc -Wall interface.c menu.c". What compiler are you using? Can you post the smallest amount of code that demonstrates this problem (i.e. fill in the ...s enough for the compilation to break on my system). I'm about to head off to lunch but should be back in an hour.

  9. #9
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by k16 View Post
    The problem is, after making the changes you suggested, I just got an increased number of undefined symbols:
    No offense but none of us are mind readers and the real problem is that you are not supplying enough code for us to diagnose your problem.
    Yes YOU know what's going on around your little 3 line snippets... we do not.

  10. #10
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    anduril's a prince...

  11. #11
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Aww shucks fellas, you're making me blush

  12. #12
    Registered User
    Join Date
    Apr 2011
    Posts
    6

    Problem solved (?)

    First of all, I want to apologize to all of you guys. I'm very sorry for not replying sooner, had to drive all the way to my hometown because of my mom's birthday

    Second, sorry again for not having provided more code nor having filled in the ellipsis' in the snippets (I really didn't have the time for the same reason). I didn't do it in the first place because, although I wasn't properly understanding the error, I was kind of sure it didn't have anything to do with it. As I read somewhere (in the forum guidelines post, probably), I didn't want to bother you with large chunks of code. Believe me guys, ignorantly (does the word even exist? Not a native speaker ) I did it with the best intentions.

    Just a note on the problem: I'm currently using a machine running mac os x 10.5.8, and had gcc 4.0.1 version installed . In the meantime I updated gcc (which was a pain as the only safe way I found to do it was by downloading the +4gb Xcode image!) and things just started compiling. Can't reason much about this, other than assuming that something was wrong with my previous installation (?). Anyway, I just wanted to clear things out. And last, thanks a bunch to all of you mike65535, anduril462, nonoob and CommonTater for taking the time to teach me something. Much obliged!

    ps: @anduril462: I'm really new here and one might claim I don't have sufficient evidence or even possibly the right to state it, but given the effort you've put into those posts, I'll just have to agree that you sir, are indeed a prince

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. undefined symbol: wurfl_ismobile
    By retrodans in forum C Programming
    Replies: 3
    Last Post: 03-30-2011, 11:46 AM
  2. fseek() changing an unrelated variable?
    By aaronvegh in forum C Programming
    Replies: 3
    Last Post: 11-21-2007, 02:30 PM
  3. Undefined symbol error??
    By Jedijacob in forum C Programming
    Replies: 10
    Last Post: 03-18-2005, 04:46 PM
  4. undefined symbol
    By sworc66 in forum C Programming
    Replies: 3
    Last Post: 09-10-2003, 06:29 AM
  5. Undefined symbol 'stdprn'
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 07-03-2002, 02:05 PM

Tags for this Thread