这个问题是关于gcc的构造函数,编译和链接是正确的,但是它不能运行。
有一个a.c:
UTEST_BEGIN()
UID(a_test)
{
printf("a test");
return true;
}
UTEST_END(a)b.c是类似的:
UTEST_BEGIN()
UID(b_test)
{
printf("b test");
return true;
}
UTEST_END(b)代码对象正在使用UID()链接一些测试函数。我的第一个版本添加了UTEST_BEGIN() UTEST_END()来封装UID(),最后我意识到UTEST_BGIN() UTEST_END()是不必要的,当我改变它们时会得到不可预测的结果。
当我改变UTEST_BEGIN(),UID(),UTEST_END()的定义时,我得到了不同的结果。
基本的想法来自can-i-auto-collect-a-list-of-function-by-c-macro!
测试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; \
}我得到了正确的结果。我可以通过一个链接调用__uti_a_test()和__uti_b_test()。实际上,__uti_xxx()链接与__m_uti_head无关,所以我想删除UTEST_BEGIN() & UTEST_END()。
运行gcc -E a.c,宏扩展为:
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;
}测试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)UID()的定义与测试1相同。我将UTEST_BEGIN() & UTEST_END()保留为空。编译和链接是正确的,但是uti_construct_a_test()和uti_construct_b_test()没有执行。
运行gcc -E a.c,宏扩展为:
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;
}utest_item_list_add_global()存在于其他.c文件中,该函数将一个节点添加到链接中:
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;
}扩展后的macor似乎也是对的。我认为问题是在链接阶段,我说的对吗?
发布于 2013-04-23 13:56:41
我发现gcc attribute((constructor))有以下事实:
Cont.c是一个包含构造函数的文件。
cons.c:
#include <stdio.h>
static void __attribute__((constructor)) construct_fun(void)
{
printf("this is a constructor\n");
}
void cons(void)
{
printf("this is cons\n");
}测试1:
main.c:
#include <stdio.h>
int main(void)
{
printf("this is main\n");
}编译方式:
gcc -c cons.c
ar cqs libcon.a cons.o
gcc main.c libcon.a输出为: this is main
测试2:
main.c:
#include <stdio.h>
extern void cons(void);
int main(void)
{
cons();
printf("this is main\n");
}编译方式:
gcc -c cons.c
ar cqs libcon.a cons.o
gcc main.c libcon.a输出:
this is a constructor
this is cons
this is main测试3:
main.c
#include <stdio.h>
int main(void)
{
printf("this is main\n");
}编译方式:
gcc main.c cons.c输出:
this is a constructor
this is main运行"gcc -v",输出:
使用内置规范。COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-redhat-linux/4.7.2/lto-wrapper目标: i686-redhat-linux配置为:../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-with-cxx--disable-build-POSTAGE1 --with-system-zlib --启用-__cxa_atexit--禁用-libunwind-异常--启用-gnu-唯一对象--启用-链接器-构建-id--使用链接器-散列样式=gnu--启用-语言=c,c++、objc、obj-c++、java、fortran、ada、go、lto --enable-插件--enable-initfini-array --enable-java-awt=gtk --dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile -enable-java-multifile mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable multilib-with-ppl --with-cloog -with-tune=generic --with-arch=i686--build=i686-redhat-linux线程模型:POSIX4.7.2- 20121109 (Red Hat 4.7.2-8) ( gcc )
我的问题是:
.c文件中只有构造函数,编译成静态库,为什么gcc会忽略这个构造函数?如何避免呢?
https://stackoverflow.com/questions/16085992
复制相似问题