c - 将 Zed Shaw 的调试宏移植到 MSVC

标签 c multithreading debugging macros strerror

我在 Zed Shaw 的网站上发现了他的调试宏,当时他的 C 书“Learn C the Hard Way”可以免费阅读。它最初是为 Linux 设计的,并且运行良好,已经使用了一段时间。

现在,我已经开始为 Windows 编写 C 代码,并且我正在使用 Visual Studio。我想在我正在处理的项目中使用这些调试宏。

问题如下: 假设我想使用检查宏来确保函数返回时没有错误。

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() 宏的指针。 但是现在我必须:

  • 要么只为这个 3 行函数创建一个全新的头文件和 C 文件,我认为这已经足够了
  • 或者我只是在调试宏的 header 中声明并实现函数,这根本不是好的 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; \
    }

我还没有测试过这段代码,所以它可能有一些错误,但它应该是一个开始。

关于c - 将 Zed Shaw 的调试宏移植到 MSVC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39642984/

相关文章:

c - 如何定位特定的 Mac OS X 版本?

c - 函数 ‘ioctl’ 的隐式声明

c# - 为调试目的获取 "critical"机器信息的库?

java - 如何调试部署在虚拟盒中的应用程序和主机操作系统中的源代码

c - C 中带有通过 FIFO 管道的指针的结构

c - lapack dgels_ 段错误 11

c++ - 寻找类似 fetch_add 的atomic<double>之类的东西

java - Eclipse 在获取 session 代码时暂停且没有断点

multithreading - 多个线程如何共享一个迭代器?

c - 是否有像 Haskell 的 Threadscope 这样的适用于 C/C++ 的良好线程跟踪器?