简体   繁体   中英

Different behavior between clang and gcc-10 when linking to static library containing global variables

I have a statically linked library, containing a global variable barvar . I can compile the library with no problems with either gcc-10 or clang (this is on macOS Catalina). Interestingly, the behavior differs between the two when I try to link it into a program that uses the library. Here's the code:

In globvars.h , int barvar is declared:

#ifndef H_GLOBVARS_H                              
#define H_GLOBVARS_H                             
  
extern int barvar;                              

#endif  

In globvars.c , int barvar is defined:

#include "globvars.h" 
int barvar;

In foo.c , the function foo sets and prints barvar :

#include <stdio.h>
#include "globvars.h"
void foo() 
{
    barvar = 10;      
    printf("barvar is: %d\n", barvar);
    return; 
}

Here's test.c , the program that uses the library:

void foo(); 
int main(int argc, char **argv)
{     
    foo();            
    return 0;
} 

When I compile and link with gcc-10, no problems:

gcc-10 -c foo.c -o foo.o
gcc-10 -c globvars.c -o globvars.o
gcc-10 -c test.c -o test.o
gcc-ar-10 rcs liblinktest.a foo.o globvars.o
gcc -o testlinkrun test2.o -L. -llinktest

When I compile and link with clang, I get an undefined symbol error at the last step:

cc -c foo.c -o foo.o
cc -c globvars.c -o globvars.o
cc -c test.c -o test.o
ar rcs liblinktest.a foo.o globvars.o
cc -o testlinkrun test2.o -L. -llinktest

with error:

Undefined symbols for architecture x86_64:
  "_barvar", referenced from:
      _foo in liblinktest.a(foo.o)

Any ideas? Interestingly, it appears the only step that has to be done with gcc-10 is compiling globvars.c . I can use clang and the clang linker for all other steps, and everything is fine. Is it possible that clang is optimizing away all the variables in globvars.c ? How can I prevent this?

As @EricPostpischil observed in this comment , the issue is that clang defaults to treating barvar as a common symbol. Either changing int barvar; to int barvar = 0; , or compiling with -fno-common , fix the issue.

Beginning with gcc-10, gcc's default behavior is -fno-common instead of -fcommon .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM