明确这些问题首先须要明确printf()函数的工作原理。
printf()维持了一个需要打印的变量栈,默认情况下,參数进栈的顺序是由右向左的。因此,參数进栈以后的内存模型例如以下图所看到的:
打印的时候,printf依照字符转换说明符规定的格式从低地址開始提取数据。直到參数打印完。
比方遇到 %f 说明符就提取8个字节的数据,遇到 %d 就提取4个字节。printf()事实上不知道參数的个数,它仅仅会依据format中的打印格式的数目依次打印堆栈中參数format后面地址的内容。
这样一来,printf()事实上存在安全隐患:它会强行读取内存的数据当作正常数据输出,没有边界检测(非常有可能产生堆溢出)。
比如这种代码:
char string[]="Hello World!";
printf("String: %s ,强行再读一次: %#p\n", string);
printf("String: %s ,强行再读一次: %#s\n", string);
输出如下:
String:Hello World! , 强行再读一次: 0X001C1073
String: Hello World! ,强行再读一次:
|