我偶然发现了一些“有趣”的东西,我无法理解为什么行为不连贯。
检查此代码。
char buf[100];
sprint(buf,"%s",bla);
简单,对。当bla
是NULL
指针时,很容易理解发生了什么。
这应该始终是段错误的??
在一台机器中,可执行文件段错误,在另一台机器上(我的开发机器),它就像往常一样。
我的devel PC正在运行Windows7
,我正在使用gcc/MingW
进行编译。崩溃的计算机是XP
,并且安装了Visual studio 6
。
为什么我的电脑没有崩溃?
答案 0 :(得分:24)
ISO C99: 7.19.6.3 The printf function
概要
#include <stdio.h>
int printf(const char * restrict format, ...);
The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf.
7.19.6.1 The fprintf function
7.19.6.1.9
If a conversion specification is invalid, the behavior is **undefined**. If any argument is
not the correct type for the corresponding conversion specification, the behavior is **undefined**.
因此,您的代码会调用未定义的行为 [(ISO C99 3.4.3)
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes **no requirements**
]
这应该始终是段错误的??
不一定,未定义的行为意味着任何都可能发生。
答案 1 :(得分:11)
这应该始终是段错误的??
没有。这会调用未定义的行为。分段错误只是调用UB的许多可能结果之一。
答案 2 :(得分:3)
因为打印空引用作为字符串是(据我所知,未经标准验证)未定义。许多系统只会在结果中输出(null)
。
与其他printf函数相同:
printf ("%s", NULL); // Outputs (null) to the console on some systems but can crash others
答案 3 :(得分:1)
除此之外,从不保证段错误。如果发生,某处出现错误;但在某处出现错误并不意味着会出现段错误。
答案 4 :(得分:1)
这应该始终是段错误的??
没有。它取决于编译器标准库附带的sprintf
函数的实现。
据我所知sprintf
规范并未说明您应提供非空地址。
答案 5 :(得分:0)
这完全取决于当时bla指向的内容。 sprintf()将执行的操作是复制bla指向的所有字符,直到遇到零(0x00)字符。
如果在达到buf [100]的限制之前遇到零字符,那么就没有段错误,因为我们没有超出buf限制。
此外,在某些系统中,如果bla指向读取访问受保护的内存区域,则一旦读取数据,它也可能导致段错误。