gpt4 book ai didi

c - 我怎样才能检查我所有的初始化函数都被调用了?

转载 作者:太空狗 更新时间:2023-10-29 14:56:52 24 4
gpt4 key购买 nike

我正在编写一个用于嵌入式的大型 C 程序。该程序中的每个模块都有一个 init() 函数(类似于构造函数)来设置其静态变量。

问题是我必须记住从 main() 调用所有这些初始化函数。如果我出于某种原因将它们注释掉,我还必须记住将它们放回去。

我有什么聪明的办法来确保所有这些函数都被调用吗?在每个 init 函数中放置一个宏,当您稍后调用 check_inited() 函数时,如果没有调用所有函数,就会向 STDOUT 发送警告。

我可以增加一个计数器,但我必须在某处维护正确数量的初始化函数,这也容易出错。

想法?

以下是我决定的解决方案,引用了该线程中几个人的意见

我的目标是确保我所有的初始化函数都被实际调用。我想要做这无需维护跨多个文件的模块列表或计数。我不能打电话正如 Nick D 所建议的那样自动调用它们,因为它们需要按特定顺序调用。

为实现这一点,每个模块中包含的宏使用 gcc constructor 属性来将 init 函数名称添加到全局列表。

init 函数主体中包含的另一个宏更新全局列表以创建一个请注意,该函数实际上已被调用。

最后,在所有初始化完成后,在 main() 中调用检查函数。

注意事项:

  1. 我选择将字符串复制到数组中。这不是绝对必要的,因为传递的函数名称在正常使用中将始终是静态字符串。如果内存力不足您可以只存储一个指向传入字符串的指针。

  2. 我的可重用实用函数库称为“nx_lib”。因此所有的“nxl”名称。

  3. 这不是世界上最高效的代码,但它仅称为启动时间,因此对我来说没关系。

  4. 每个模块需要添加两行代码。如果省略其中一个,检查功能会让你知道。

  5. 您可以将构造函数设为静态,这样就无需为其指定一个在整个项目中唯一的名称。

  6. 此代码仅经过轻微测试,而且已经很晚了,所以请在信任它之前仔细检查。

感谢您:

pierr 向我介绍了 constructor 属性。

Nick D 演示了 ## 预处理器技巧并为我提供了框架。

tod frye 一种基于链接器的巧妙方法,适用于许多编译器。

其他人帮助和分享有用的花絮。

nx_lib_public.h

这是我的库头文件的相关片段

#define NX_FUNC_RUN_CHECK_NAME_SIZE 20

typedef struct _nxl_function_element{
char func[NX_FUNC_RUN_CHECK_NAME_SIZE];
BOOL called;
} nxl_function_element;

void nxl_func_run_check_add(char *func_name);
BOOL nxl_func_run_check(void);
void nxl_func_run_check_hit(char *func_name);

#define NXL_FUNC_RUN_CHECK_ADD(function_name) \
void cons_ ## function_name() __attribute__((constructor)); \
void cons_ ## function_name() { nxl_func_run_check_add(#function_name); }

nxl_func_run_check.c

这是调用添加函数名称并稍后检查它们的库代码。

#define MAX_CHECKED_FUNCTIONS 100

static nxl_function_element m_functions[MAX_CHECKED_FUNCTIONS];
static int m_func_cnt = 0;


// call automatically before main runs to register a function name.
void nxl_func_run_check_add(char *func_name)
{
// fail and complain if no more room.
if (m_func_cnt >= MAX_CHECKED_FUNCTIONS) {
print ("nxl_func_run_check_add failed, out of space\r\n");
return;
}

strncpy (m_functions[m_func_cnt].func, func_name,
NX_FUNC_RUN_CHECK_NAME_SIZE);

m_functions[m_func_cnt].func[NX_FUNC_RUN_CHECK_NAME_SIZE-1] = 0;

m_functions[m_func_cnt++].called = FALSE;
}

// call from inside the init function
void nxl_func_run_check_hit(char *func_name)
{
int i;

for (i=0; i< m_func_cnt; i++) {
if (! strncmp(m_functions[i].func, func_name,
NX_FUNC_RUN_CHECK_NAME_SIZE)) {
m_functions[i].called = TRUE;
return;
}
}

print("nxl_func_run_check_hit(): error, unregistered function was hit\r\n");
}

// checks that all registered functions were called
BOOL nxl_func_run_check(void) {
int i;
BOOL success=TRUE;

for (i=0; i< m_func_cnt; i++) {
if (m_functions[i].called == FALSE) {
success = FALSE;
xil_printf("nxl_func_run_check error: %s() not called\r\n",
m_functions[i].func);
}
}
return success;
}

solo.c

这是一个需要初始化的模块的例子

#include "nx_lib_public.h"

NXL_FUNC_RUN_CHECK_ADD(solo_init)
void solo_init(void)
{
nxl_func_run_check_hit((char *) __func__);

/* do module initialization here */
}

最佳答案

您可以使用 gcc的扩展 __attribute__((constructor)) 如果 gcc 适合你的项目。

#include <stdio.h>
void func1() __attribute__((constructor));
void func2() __attribute__((constructor));

void func1()
{
printf("%s\n",__func__);
}

void func2()
{
printf("%s\n",__func__);
}

int main()
{
printf("main\n");
return 0;
}

//the output
func2
func1
main

关于c - 我怎样才能检查我所有的初始化函数都被调用了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1485198/

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