【问题标题】:warning: format not a string literal and no format arguments警告:格式不是字符串文字,也没有格式参数
【发布时间】:2011-05-24 02:06:42
【问题描述】:

我想删除我在这行代码中得到的警告,

FILE *fil;
char *imp;
(...)
fprintf(fil,imp);

问题是当我这样做时,它会在文件上准确地写入我想要的内容,但如果我应用 %s 格式,它就不会,像这样

fprintf(fil, "%s", imp);

【问题讨论】:

  • imp 包含什么?
  • 如果将 fprintf 替换为 fputs(imp, fil); 会发生什么?
  • 一个字符串,假设像这样 imp="test";
  • @Unzi:如果imp 不包含任何格式说明符(即%...),那么您的两个调用将相同。你到底在观察什么? “如果我应用格式 %s 它不会”是什么意思?
  • “它不喜欢这个”是什么意思?编译器错误?你没有看到任何输出? 什么?

标签: c++ c format warnings printf


【解决方案1】:

此警告是 gcc 告诉您它无法验证 printf 样式函数(printf、fprintf...等)的格式字符串参数的方式。当编译器无法手动查看字符串并确保在运行时一切都按预期进行时,会生成此警告。让我们看几个例子。

案例1.这个字符串可以在编译时验证,编译器会在没有警告的情况下允许它:

printf("This string has no format");

情况 2:对于这种情况,编译器可以检测到您有格式说明符,并会发出不同的警告。在我的机器上它说“警告:格式参数太少”。

// This will most probably crash your machine
printf("Not a safe string to %s"); 

案例 3。现在这有点像您的情况。您正在获取运行时生成的字符串并尝试打印它。您收到的警告是编译器警告您字符串中可能存在格式说明符。比如说“bad%sdata”。在这种情况下,运行时将尝试访问不存在的参数以匹配 %s。更糟糕的是,这可能是用户试图利用您的程序(导致其读取不安全的数据)。

char str[200];
scanf("%s", str)
printf(str)

【讨论】:

  • 调用一个需要 const char * 的函数并给它一个 char * 不会引起警告,恕我直言
  • 我并不是建议将字符串强制转换为 const。我提到需要指定第二个参数来修复警告。
  • 必须“指定参数”是什么意思?
  • @Sanjit Saluja:很好的解释。那么如何告诉 GCC 我知道我在做什么来抑制该警告呢?
  • 为了避免警告和可能的攻击媒介,您还可以使用printf("%s", str);
【解决方案2】:

虽然从技术上讲,用字符串调用类似 printf 的函数并没有什么问题,但它仍然是不好的做法,因为字符串可能包含像 %s 这样的格式标记。例如,如果imp%s test,就会发生不好的事情。

如果你只想打印imp而不格式化,你应该使用fputs(imp, fil)(注意颠倒的参数)。

【讨论】:

  • 更糟糕的是:如果用户可以指定 imp 字符串,他也许可以使用 %n 格式标记来覆盖内存。这称为格式字符串攻击,可用于运行注入代码。
  • fputs 可以写出没有 % 格式的字符串。
  • 'sans' 是法语的“没有”。他的意思是“没有 % 格式”吗?
【解决方案3】:

我认为the accepted answer 解释得很好。基本上,正如the documentation 也表明的那样,编译器不能保证字符串变量(在这种情况下为imp)是字符串文字。如果您不关心安全性,您可以通过放置

来禁用此警告
#ifdef _WIN32
#pragma warning (disable : 4774)
#endif

在代码的标题或 CMake 中:

if (CMAKE_C_COMPILER_ID STREQUAL "MSVC")
  set(CMAKE_C_FLAGS "/wd4774") 
endif()

【讨论】:

    猜你喜欢
    • 2010-12-13
    • 2015-01-27
    • 2013-04-07
    • 1970-01-01
    • 2014-12-23
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    相关资源
    最近更新 更多