c - GCC constructor NOT execute -


this question gcc constructor, compile & link right, not run.

there a.c:

utest_begin() uid(a_test) {     printf("a test");     return true; } utest_end(a) 

b.c simlar:

utest_begin() uid(b_test) {     printf("b test");     return true; } utest_end(b) 

the code object using uid() link test functions. first version add utest_begin() utest_end() enclose uid(), @ last realize utest_bgin() utest_end() isn't necessary, when change them unpredicated result.

when change definition of utest_begin(), uid(), utest_end(), got different result.

the basic idea come can-i-auto-collect-a-list-of-function-by-c-macro!

test 1:

#define utest_begin()                                   \ static const bool __m_en = true;                        \ static struct __uti *__m_uti_head = null;    bool utest_item_list_add_global(struct __uti *uti); #define uid(f)                                                          \ static bool __uti_##f(void);                                            \ __attribute__((constructor))                                            \ static void uti_construct_##f(void)                                     \ {                                                                       \     printf("%s\n", #f); \     static struct __uti __m_uti_##f = {null, this_file_id, __uti_##f, #f };       \     utest_item_list_add_global(&__m_uti_##f);                           \ }                                                                       \ static bool __uti_##f(void)   bool unit_test_item_pump_do(int file_id, bool (*f)(void), const char *f_name); #define utest_end(file_name)                                            \ bool unit_test_##file_name(void)                                        \ {                                                                       \     if (!__m_en)                                                        \             return true;                                                \     struct __uti *cur;                                                  \     for(cur = __m_uti_head; cur; cur = cur->next) {                     \             unit_test_set_run_last_line(__line__);                      \             if (!unit_test_item_pump_do(this_file_id, cur->f, cur->f_name)) \                     return false;                                       \     }                                                                   \     return true;                                                        \ } 

i got right result. can call __uti_a_test() , __uti_b_test() through link. in fact, __uti_xxx() link not realated __m_uti_head, want remove utest_begin() & utest_end().

run gcc -e a.c, macro extend as:

static const bool __m_en = 1;  static struct __uti *__m_uti_head = ((void *)0);  static bool __uti_a_test(void);  __attribute__((constructor))  static void uti_construct_a_test(void)  {      static struct __uti __m_uti_a_test = {((void *)0), file_id_a, __uti_a_test, "a_test" };      utest_item_list_add_global(&__m_uti_a_test);  }  static bool __uti_a_test(void) {     printf("a test");     return 1; }   bool unit_test_a(void)  {      if (!__m_en)          return 1;      struct __uti *cur;      for(cur = __m_uti_head; cur; cur = cur->next) {          unit_test_set_run_last_line(19);          if (!unit_test_item_pump_do(file_id_a, cur->f, cur->f_name))              return 0;      }      return 1;  } 

test 2:

#define utest_begin()    bool utest_item_list_add_global(struct __uti *uti); #define uid(f)                                                          \ static bool __uti_##f(void);                                            \ __attribute__((constructor))                                            \ static void uti_construct_##f(void)                                     \ {                                                                       \     printf("%s\n", #f);                                                 \     static struct __uti __m_uti_##f = {null, this_file_id, __uti_##f, #f };       \     utest_item_list_add_global(&__m_uti_##f);                           \ }                                                                       \ static bool __uti_##f(void)   #define utest_end(file_name) 

the definition of uid() same test 1. keep utest_begin() & utest_end() blank. compile & link right, uti_construct_a_test() & uti_construct_b_test() not execute.

run gcc -e a.c, macro extend as:

static bool __uti_a_test(void);  __attribute__((constructor))  static void uti_construct_a_test(void)  {      static struct __uti __m_uti_a_test = {((void *)0), file_id_a, __uti_a_test, "a_test" };      utest_item_list_add_global(&__m_uti_a_test);  }  static bool __uti_a_test(void) {     printf("a test");     return 1; } 

the utest_item_list_add_global() exist in other .c file, function add node link:

static struct __uti *m_uti_head = null; bool utest_item_list_add_global(struct __uti *uti) {         if (null == m_uti_head) {                 m_uti_head = uti;                 return true;         }          struct __uti *tail = m_uti_head;         while (null != tail->next)                 tail = tail->next;         tail->next = uti;         return true; } 

the expanded macor seem right. think problem in link stage, right?

i found gcc attribute((constructor)) have below fact:

cons.c file contain constructor function.

  1. if constructor exist in cons.c file, compile static library, link main(), constructor ignore.
  2. if function called in main.c exist in cons.c, compile cons.c static library, link main(), constructor called before main.
  3. if use "gcc main.c cons.c", constructor called before main.

cons.c:

#include <stdio.h> static void __attribute__((constructor)) construct_fun(void) {         printf("this constructor\n"); }  void cons(void) {         printf("this cons\n"); } 

test 1:

main.c:

#include <stdio.h> int main(void) {         printf("this main\n"); } 

compile by:

gcc -c cons.c ar cqs libcon.a cons.o gcc main.c libcon.a 

output is: main

test 2:

main.c:

#include <stdio.h> extern void cons(void); int main(void) {         cons();         printf("this main\n"); } 

compile by:

gcc -c cons.c ar cqs libcon.a cons.o gcc main.c libcon.a 

output:

this constructor cons main 

test 3:

main.c

#include <stdio.h> int main(void) {         printf("this main\n"); } 

compile by:

gcc main.c cons.c 

output:

this constructor main 

run "gcc -v", output:

using built-in specs. collect_gcc=gcc collect_lto_wrapper=/usr/libexec/gcc/i686-redhat-linux/4.7.2/lto-wrapper target: i686-redhat-linux configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --disable-build-with-cxx --disable-build-poststage1-with-cxx --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux thread model: posix gcc version 4.7.2 20121109 (red hat 4.7.2-8) (gcc)

my question is:

only constructor exist in .c file, compile static library, why gcc ignore construct? how avoid it?


Comments

Popular posts from this blog

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -

node.js - Bad Request - node js ajax post -