我在他的网站上找到了Zed Shaw的调试宏,当时他的C书《艰难地学习C》可以免费阅读。它最初是为Linux设计的,运行良好,已经使用了一段时间。
现在,我已经开始为Windows编写C代码,并且正在使用Visual Studio。我想在我正在处理的项目中使用这些调试宏。
问题如下:
假设我想使用check宏来确保函数返回时没有错误。
display = al_create_display(640, 480);
check(display, "Failed to create display");
将要使用的宏的定义如下:
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
但是,我遇到的问题是Visual Studio将
strerror()
标记为已弃用并中止编译。我计划在项目中使用线程,所以我不想走“忽略”的路线,如果可能的话。我所做的是创建了一个
clean_errno()
函数,该函数执行与宏相同的操作,但使用全局缓冲区变量并调用strerror_s()
复制到该函数中,然后返回指向log_err()
宏的指针。但是现在我必须:
或者为这个三行函数创建一个全新的头文件和C文件,我认为它非常丰富
或者,我只是在调试宏的头中声明并实现该函数,这根本不被认为是良好的C实践,而且也非常难看。
有没有其他我不知道的技巧/技巧可以提供一个优雅而简单的解决方案呢?
最佳答案
Strerror不推荐使用,因为它不是线程安全的。如果您不关心这个事实,那么您可能可以在VS中找到一些选项来关闭这个警告。
但使用sterror_s()实现线程安全版本也同样简单。记住,宏不仅仅可以计算表达式,还可以在宏中分配缓冲区:
#define check(A, M, ...) \
if(!(A)) { \
char _buffer[128]; \
strerror_s(_buffer, 128, errno); \
fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " (M) "\n", __FILE__, \
__LINE__, errno? _buffer : "None", ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
我还没有测试过这段代码,所以它可能有一些错误,但这应该是一个开始。