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.
- if constructor exist in cons.c file, compile static library, link main(), constructor ignore.
- if function called in main.c exist in cons.c, compile cons.c static library, link main(), constructor called before main.
- 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
Post a Comment