gpt4 book ai didi

c++ - 错误地将字符串传递给 printf 样式的日志函数时遗漏错误

转载 作者:搜寻专家 更新时间:2023-10-31 02:16:54 24 4
gpt4 key购买 nike

对于任何大中型项目来说,将printf替换为自定义日志功能是很常见的。这是一个最小的 C++ 示例及其用法:

#include <stdio.h>
#include <stdarg.h>
#include <string>

void log_printf(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap); // real code obviously does something fancier
va_end(ap);
}

int main() {
std::string x = "Hello";

// correct code
printf("String is %s\n", x.c_str());
log_printf("String is %s\n", x.c_str());

// incorrect code
printf("String is %s\n", x); // bad line 1
log_printf("String is %s\n", x); // bad line 2
}

简单记录器接收可变数量的参数并调用 vprintf 将它们输出到标准输出。 “正确代码”下的行演示了此记录器的正确用法。我的问题涉及“错误”行,其中错误地传递了字符串对象而不是指向字符缓冲区的指针。

在 GCC 4.6 下(在 Linux 下测试),坏行都不能编译,这是一件好事,因为我想捕捉到这种不正确的用法。错误是:

error: cannot pass objects of non-trivially-copyable type ‘std::string {aka struct std::basic_string<char>}’ through ‘...’

但是在 GCC 5.1 中,显然可以传递非平凡可复制的对象,并且编译成功。如果我使用 -Wall,那么只有“bad line 1”会发出关于意外参数类型的警告,但是带有 log_printf 的“bad line 2”在任何情况下都可以毫无问题地编译。不用说,两条线都会产生垃圾输出。

我可以用 -Wall -Werror 捕捉到“坏线 1”,但是“坏线 2”呢?我怎样才能让它也产生编译错误?

最佳答案

对于您自己的功能,您需要使用 common function attribute调用格式:

void log_printf(const char* fmt, ...) __attribute__((format (printf, 1, 2)));

void log_printf(const char* fmt, ...) {
...
}

请注意,该属性必须在函数声明中设置,而不是定义。

format 属性的第一个参数是样式,在本例中为 printf(scanf 也是可能的,对于像这样工作的函数scanf), 第二个参数是格式字符串,第三个参数是省略号 ... 所在的位置。它将帮助 GCC 检查格式字符串,就像标准 printf 函数一样。

这是一个 GCC 扩展,尽管其他一些编译器已经采用它来与 GCC 兼容,最著名的是 Intel C 编译器 ICC 和 Clang(在 OSX 和一些 BSD 变体上使用的标准编译器)。 Visual Studio 编译器没有这个扩展,我不知道 Visual C++ 有类似的东西。

关于c++ - 错误地将字符串传递给 printf 样式的日志函数时遗漏错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36407973/

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