为什么这个段错误没有
我偶然发现了一些“有趣”的东西,但我无法解释为什么这种行为不连贯。
检查此代码。
char buf[100];
sprint(buf,"%s",bla);
简单,对。当 bla
是 NULL
指针时,很容易理解发生了什么。
这应该总是出现段错误吧!?
在一台机器上,可执行文件出现段错误,在另一台机器(我的开发机器)上,一切照常。
我的开发 PC 运行的是 Windows7
,并且我使用 gcc/MingW
进行编译。发生崩溃的计算机是 XP
,并且安装了 Visual studio 6
。
为什么这在我的电脑上不会崩溃?
I stumbled across something "interesting" and I cant put my finger why the behaviour isn't coherent.
Check this code.
char buf[100];
sprint(buf,"%s",bla);
Simple, right. It's easy to understand what is going on when bla
is a NULL
pointer.
This should always segfault right!?
In one machine the executable segfaults, on another (my development machine), it's just business as usual.
My devel PC is running Windows7
and I'm compiling with gcc/MingW
. The computer where this is crashing is XP
and it does have Visual studio 6
installed.
Why doesn't this crash on my PC?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
ISO C99:7.19.6.3 printf 函数
概要
printf 函数相当于 fprintf,但参数 stdout 插入到 printf 的参数之前。
< code>7.19.6.1 fprintf 函数
7.19.6.1.9
如果转换规范无效,则行为**未定义**。如果有任何参数是
不是相应转换规范的正确类型,该行为**未定义**。
因此您的代码调用未定义行为 [
(ISO C99 3.4.3)
]使用不可移植或错误的程序构造或错误数据时的行为,
本国际标准对此没有强加**无要求**
不一定,未定义的行为意味着任何事情都可能发生。
ISO C99: 7.19.6.3 The printf function
Synopsis
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**.
So your code invokes Undefined Behavior [
(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**
Not necessarily, Undefined Behavior means anything can happen.
不。这会调用未定义的行为。分段错误只是调用 UB 的众多可能结果之一。
No. This invokes undefined behavior. A segmentation fault is but one of many possible results of invoking UB.
因为将空引用打印为字符串是未定义的(据我所知,尚未通过标准验证)。许多系统只会在结果中输出
(null)
。与其他 printf 函数相同:
Because printing a null reference as a string is (as far as I know, haven't verified with standards) undefined. Many systems will just output
(null)
in the result.It's the same with the other printf functions:
除此之外,永远无法保证出现段错误。如果发生的话,说明某个地方有错误;但某个地方出现错误并不意味着存在段错误。
Apart from that, a segfault is never guaranteed. If it occurs, there is an error somewhere; but having an error somewhere doesn't imply a segfault.
不会。这取决于编译器标准库附带的 sprintf 函数的实现。
据我所知,
sprintf
规范并未规定您应该提供非空地址。No. It depends on the implementation of the
sprintf
function that came with the standard library of the compiler.As far as I know
sprintf
specification doesn't say you should provide a non-null address.这完全取决于 bla 当时指向的是什么。
sprintf() 将复制 bla 指向的所有字符,直到遇到零 (0x00) 字符。
如果它在达到 buf[100] 限制之前遇到零字符,则不会出现段错误,因为我们没有写入超出 buf 限制的内容。
另外,在某些系统中,如果 bla 指向读访问受保护的内存区域,则在读取数据后也可能会导致段错误。
It all depends on what bla is pointing to at the time.
What sprintf() will do is copy all of the characters pointed to by bla until it encounters a zero (0x00) character.
If it encounters a zero character before it reaches the limit of buf[100], then, there's no segfault because we are not writing beyond the buf limit.
Also, in some systems, if bla points to a read-access protected memory region, it may also cause a segfault as soon as the data is read.