gpt4 book ai didi

c - GCC构造函数不执行

转载 作者:行者123 更新时间:2023-12-04 02:58:00 28 4
gpt4 key购买 nike

这道题是关于gcc构造函数的,编译&链接是对的,但是没有运行。

有空调:

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;
}

扩展的宏似乎是正确的。我认为问题出在链接阶段,对吗?

最佳答案

我发现 gcc attribute((constructor)) 有以下事实:

cons.c 是一个包含构造函数的文件。

  1. 如果cons.c文件中只有constructor,编译成静态库,然后用main()链接,constructor会被忽略。
  2. 如果cons.c中存在在main.c中调用的任何函数,则将cons.c编译为静态库,然后将其与main()链接,构造函数将在main之前调用。
  3. 如果使用“gcc main.c cons.c”,构造函数将在main之前被调用。

缺点:

#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:

主.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

输出是: 这是主要的

测试 2:

主.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:

主.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_GCC=海湾合作委员会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-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线程模型:posixgcc 版本 4.7.2 20121109 (Red Hat 4.7.2-8) (GCC)

我的问题是:

.c文件中只有构造函数存在,将其编译为静态库,为什么gcc忽略构造函数?如何避免?

关于c - GCC构造函数不执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16085992/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com