l******d 发帖数: 530 | 1 #include
int main(){
printf("Hello %s\n", NULL);
fflush(stdout);
printf("%s\n", NULL);
fflush(stdout);
return 0;
}
在linux上用gcc编译运行结果为
Hello (null)
Segmentation fault
什么原理? |
X****r 发帖数: 3557 | 2 gcc optimizes the second case to call puts() instead, which can't handle
NULL.
%s in printf isn't required to be able to handle NULL anyway, so just don't
do it.
【在 l******d 的大作中提到】 : #include : int main(){ : printf("Hello %s\n", NULL); : fflush(stdout); : printf("%s\n", NULL); : fflush(stdout); : return 0; : } : 在linux上用gcc编译运行结果为 : Hello (null)
|
p*********t 发帖数: 2690 | 3 找函数printf()的源码读读就知道了。
【在 l******d 的大作中提到】 : #include : int main(){ : printf("Hello %s\n", NULL); : fflush(stdout); : printf("%s\n", NULL); : fflush(stdout); : return 0; : } : 在linux上用gcc编译运行结果为 : Hello (null)
|
f*******n 发帖数: 12623 | 4 try
gcc -fno-builtin-printf |
l******d 发帖数: 530 | 5 刚发现格式串里面的\n是关键
printf("%s", NULL)执行没出错,输出(null)
print("%s\n", NULL)执行错了,Seg. fault
搞不懂了
t
【在 X****r 的大作中提到】 : gcc optimizes the second case to call puts() instead, which can't handle : NULL. : %s in printf isn't required to be able to handle NULL anyway, so just don't : do it.
|
X****r 发帖数: 3557 | 6 拜托,你看了我的贴没有啊。
我不是说了print("%s\n", NULL);被优化成puts(NULL);了吗。
%s本来就没有规定可以处理空指针,gcc怎么做都不算错,没什么好琢磨的。
【在 l******d 的大作中提到】 : 刚发现格式串里面的\n是关键 : printf("%s", NULL)执行没出错,输出(null) : print("%s\n", NULL)执行错了,Seg. fault : 搞不懂了 : : t
|
l******d 发帖数: 530 | 7 看了你的帖子,还有一点没懂:
printf("%s",NULL)(%S后没有\n)没有被优化成puts(NULL),所以没有Seg. fault,
是这样子吗?
【在 X****r 的大作中提到】 : 拜托,你看了我的贴没有啊。 : 我不是说了print("%s\n", NULL);被优化成puts(NULL);了吗。 : %s本来就没有规定可以处理空指针,gcc怎么做都不算错,没什么好琢磨的。
|
X****r 发帖数: 3557 | 8 puts会在字符串最后输出\n,所以printf("%s",NULL)没法优化成puts(NULL)啊。
【在 l******d 的大作中提到】 : 看了你的帖子,还有一点没懂: : printf("%s",NULL)(%S后没有\n)没有被优化成puts(NULL),所以没有Seg. fault, : 是这样子吗?
|
l******d 发帖数: 530 | 9 偶像你懂的太多了,谢谢。btw,这些东西哪里有系统的讲解的,还是只能裸看源代码吗
【在 X****r 的大作中提到】 : puts会在字符串最后输出\n,所以printf("%s",NULL)没法优化成puts(NULL)啊。
|
l******d 发帖数: 530 | 10 偶像狠狠的鞭答我吧,我想了一圈又糊涂了
为什么会"%s\n"被优化NULL,而"%s"就不会呢。
我知道puts会在字符串最后输出\n,但在"%s\n"后面加个"\n"怎么就成了NULL呢?
【在 X****r 的大作中提到】 : puts会在字符串最后输出\n,所以printf("%s",NULL)没法优化成puts(NULL)啊。
|
|
|
X****r 发帖数: 3557 | 11 printf和puts都是标准系统函数,你找个C标准就有详细定义。
不用琢磨用%s输出NULL的事,只要知道(从上面printf的文档里)不能这么用就行了。
软件工程的核心是开发效率,完全没有必要自己挖个坑去跳。
码吗
【在 l******d 的大作中提到】 : 偶像你懂的太多了,谢谢。btw,这些东西哪里有系统的讲解的,还是只能裸看源代码吗
|
l******d 发帖数: 530 | 12 我是看到这个文章http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41776
想不通
【在 X****r 的大作中提到】 : printf和puts都是标准系统函数,你找个C标准就有详细定义。 : 不用琢磨用%s输出NULL的事,只要知道(从上面printf的文档里)不能这么用就行了。 : 软件工程的核心是开发效率,完全没有必要自己挖个坑去跳。 : : 码吗
|
t****t 发帖数: 6806 | 13 你有什么想不通的, 不是都说了the testcase is invalid吗?
invalid的东西你为什么要去想通它?
【在 l******d 的大作中提到】 : 我是看到这个文章http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41776 : 想不通
|
X****r 发帖数: 3557 | 14 因为对于任何str,printf("%s\n", str);等价于puts(str),所以gcc作了优化,
这里正好str是NULL。printf("%s", str);并不等价于puts(str),所以真正的
printf被调用了,而glibc里的printf是可以处理NULL的。
其实从第一贴开始我就在说这个,要是还不清楚的话我实在不知道该怎么讲了。
【在 l******d 的大作中提到】 : 偶像狠狠的鞭答我吧,我想了一圈又糊涂了 : 为什么会"%s\n"被优化NULL,而"%s"就不会呢。 : 我知道puts会在字符串最后输出\n,但在"%s\n"后面加个"\n"怎么就成了NULL呢?
|
l******d 发帖数: 530 | 15 我之前是想不通为什么这个testcase是invalid的
【在 t****t 的大作中提到】 : 你有什么想不通的, 不是都说了the testcase is invalid吗? : invalid的东西你为什么要去想通它?
|
t****t 发帖数: 6806 | 16 下一句就是原因("you can't pass NULL to %s"), 这也想不通吗?
【在 l******d 的大作中提到】 : 我之前是想不通为什么这个testcase是invalid的
|
i***c 发帖数: 301 | |
l******d 发帖数: 530 | 18 可是他没说为什么can't pass NULL to "%s\n", but can to "%s"呀
【在 t****t 的大作中提到】 : 下一句就是原因("you can't pass NULL to %s"), 这也想不通吗?
|
t****t 发帖数: 6806 | 19 he meant you can't pass NULL to %s, no matter whether you have \n after it.
【在 l******d 的大作中提到】 : 可是他没说为什么can't pass NULL to "%s\n", but can to "%s"呀
|
l******d 发帖数: 530 | 20 那为什么
printf("%s", NULL); //not fault
printf("%s\n%s\n", NULL, NULL); //not fault
又可以呢?这个我看着原帖楞是想不明白,直到Xentar解释了:printf("%s\n", str)
被优化成puts(str),而printf("%s", str)不被优化。
【在 t****t 的大作中提到】 : he meant you can't pass NULL to %s, no matter whether you have \n after it.
|
|
|
X****r 发帖数: 3557 | 21 唉,敢情我白讲了啊。
在printf里用%s来打印NULL是错误的,会导致未定义的结果,无论是
printf("%s", NULL);还是printf("%s\n", NULL);
注意未定义的结果包括“正确”的结果,但这是没有保证的,回头gcc一升级说不定
printf("%s", NULL);也seg fault了。琢磨这个基本上没有任何用处,你只
需要知道不用%s来打印NULL就行了。
【在 l******d 的大作中提到】 : 那为什么 : printf("%s", NULL); //not fault : printf("%s\n%s\n", NULL, NULL); //not fault : 又可以呢?这个我看着原帖楞是想不明白,直到Xentar解释了:printf("%s\n", str) : 被优化成puts(str),而printf("%s", str)不被优化。
|
t****t 发帖数: 6806 | 22 both are invalid, no matter whether you get "correct" result or not.
【在 l******d 的大作中提到】 : 那为什么 : printf("%s", NULL); //not fault : printf("%s\n%s\n", NULL, NULL); //not fault : 又可以呢?这个我看着原帖楞是想不明白,直到Xentar解释了:printf("%s\n", str) : 被优化成puts(str),而printf("%s", str)不被优化。
|
S*******s 发帖数: 13043 | 23 you are just waste your time to try that. just remeber it is illegal and
should be advoid. the specific implementation of a certain compilor does not
make any sense at all.
【在 l******d 的大作中提到】 : 刚发现格式串里面的\n是关键 : printf("%s", NULL)执行没出错,输出(null) : print("%s\n", NULL)执行错了,Seg. fault : 搞不懂了 : : t
|
b*****e 发帖数: 474 | 24 对,这是跟gcc 有关的。一般没有优化的时候,会call strlen(),
可能会seg fault。好像说是这种字符串的库函数当参数为空指针
的时候,结果没有定义。所以你看到奇怪的行为也是可以的。
t
【在 X****r 的大作中提到】 : gcc optimizes the second case to call puts() instead, which can't handle : NULL. : %s in printf isn't required to be able to handle NULL anyway, so just don't : do it.
|
t****n 发帖数: 324 | 25 I beg a differ.
搞技术就是要有楼主这种打破沙锅问(这里问及可是问己也可是问人)到底的精神。
not
【在 S*******s 的大作中提到】 : you are just waste your time to try that. just remeber it is illegal and : should be advoid. the specific implementation of a certain compilor does not : make any sense at all.
|
S*******s 发帖数: 13043 | 26 no. it does not make any sense, period.
【在 t****n 的大作中提到】 : I beg a differ. : 搞技术就是要有楼主这种打破沙锅问(这里问及可是问己也可是问人)到底的精神。 : : not
|
t****n 发帖数: 324 | 27 知其然是不够的,还要知其所以然,光靠记是得过且过的态度,迟早要被bite back。
【在 S*******s 的大作中提到】 : no. it does not make any sense, period.
|
t****t 发帖数: 6806 | 28 你要知其所以然的话, 自己去拿gcc的源码边读边上吊呗, 不要拉着别人一起.
这年头, 写两行程序也能算是搞技术的了, 真是世界不一样了啊.
【在 t****n 的大作中提到】 : 知其然是不够的,还要知其所以然,光靠记是得过且过的态度,迟早要被bite back。
|
a****l 发帖数: 8211 | 29 先要把方向了解正确,然后努力才行,否则就是越努力反而离目标越远.具体的说,在这个
问题上,先是要清楚的理解问题的性质(undefined behavior),然后才能去研究为什么,
比如看编译器的源代码,否则就会引申出一堆莫名其妙的稀奇古怪的"经验",比如有的人
可能说"\n"会影响程序的正确性.这就是猪大牛为什么说不要去考虑这些问题的原因,因
为基本上会问这些问题的人都还不清楚到底应该怎么去研究这些问题,花时间研究的话
往往有害而无益.
【在 t****n 的大作中提到】 : 知其然是不够的,还要知其所以然,光靠记是得过且过的态度,迟早要被bite back。
|
s******e 发帖数: 1751 | 30 read POSIX standard. I think the behavior is not defined, i.e. compile can
do whatever it wants to do.
【在 t****t 的大作中提到】 : 你要知其所以然的话, 自己去拿gcc的源码边读边上吊呗, 不要拉着别人一起. : 这年头, 写两行程序也能算是搞技术的了, 真是世界不一样了啊.
|
|
|
F********g 发帖数: 475 | 31 读标准,MACHINE DEPENDENT,IMPLEMENTATION DEPENDENT不碰就是了。
一般上班了大点的铺子有CODING STANDARD。好处是遵守了不容易出错,坏处是编几年
下来还是不清楚边边角角的蹊跷特性。 |
m*****e 发帖数: 4193 | 32
精神可嘉,方法错误。
想知其所以然的话就自己花时间去钻研,而不是要别人一遍一遍解释,实在不行还有
google。
【在 t****n 的大作中提到】 : 知其然是不够的,还要知其所以然,光靠记是得过且过的态度,迟早要被bite back。
|
b***i 发帖数: 3043 | 33 这个问题和组里面自己定的风格还是有很大区别的。楼主问的类似于,我在15街闯红灯
每次都没事,在14街就不行,就被摄像头拍下来了,拿了罚单,这是为什么?
大伙回答,两个街的摄像由不同的警察局审查。但是不应该研究这个问题,不闯红灯就行
了。而且,可以在不知道两个街由不同警察管理的情况下,只要不闯红灯,就可以完成
送饭的任务。
哪些方向可以研究呢?如果你没闯红灯却被误判了,就类似于编译器的错误了,这种情
况下是值得研究的。很多单片机的编译器都有错误,你了解了对工作是有好处的。但是
,如果编译器没有问题,写了错误的代码结果却没有太离谱,那只不过是运气,是没有
必要纠缠的。
【在 F********g 的大作中提到】 : 读标准,MACHINE DEPENDENT,IMPLEMENTATION DEPENDENT不碰就是了。 : 一般上班了大点的铺子有CODING STANDARD。好处是遵守了不容易出错,坏处是编几年 : 下来还是不清楚边边角角的蹊跷特性。
|
t****t 发帖数: 6806 | 34 唉, 比喻很好, 但是我实在是不愿意一次一次讲了...
【在 b***i 的大作中提到】 : 这个问题和组里面自己定的风格还是有很大区别的。楼主问的类似于,我在15街闯红灯 : 每次都没事,在14街就不行,就被摄像头拍下来了,拿了罚单,这是为什么? : 大伙回答,两个街的摄像由不同的警察局审查。但是不应该研究这个问题,不闯红灯就行 : 了。而且,可以在不知道两个街由不同警察管理的情况下,只要不闯红灯,就可以完成 : 送饭的任务。 : 哪些方向可以研究呢?如果你没闯红灯却被误判了,就类似于编译器的错误了,这种情 : 况下是值得研究的。很多单片机的编译器都有错误,你了解了对工作是有好处的。但是 : ,如果编译器没有问题,写了错误的代码结果却没有太离谱,那只不过是运气,是没有 : 必要纠缠的。
|
t****n 发帖数: 324 | 35 楼上那两三位,早年的填鸭式教育把你们教的固步自封,亦步亦趋了。
估计楼主没你们说的那么多想法,就是想弄个明白,你们看来也并不真正明白为啥不能
那样做,却觉得知道不能那么做就有资格教训别人了。
同情你们。
【在 t****t 的大作中提到】 : 唉, 比喻很好, 但是我实在是不愿意一次一次讲了...
|
t****t 发帖数: 6806 | 36 你觉得你挺清楚就解释给他听呗, 说这么多废话干什么.
我在这里义务给人答疑的时候你还不知道在哪儿呢. 现在我觉得答了这么些年疑也没什
么意思还经常要遭人白眼, 刚好换你来了. 请!
【在 t****n 的大作中提到】 : 楼上那两三位,早年的填鸭式教育把你们教的固步自封,亦步亦趋了。 : 估计楼主没你们说的那么多想法,就是想弄个明白,你们看来也并不真正明白为啥不能 : 那样做,却觉得知道不能那么做就有资格教训别人了。 : 同情你们。
|
t****n 发帖数: 324 | 37 大半夜的,这么大脾气干吗?懂就是懂,不懂就是不懂。
不懂装懂,和懂装不懂,都是不对的,你说呢?
【在 t****t 的大作中提到】 : 你觉得你挺清楚就解释给他听呗, 说这么多废话干什么. : 我在这里义务给人答疑的时候你还不知道在哪儿呢. 现在我觉得答了这么些年疑也没什 : 么意思还经常要遭人白眼, 刚好换你来了. 请!
|
t****t 发帖数: 6806 | 38 你说得对啊, 所以我不是请你解释给他听么. 我顺便听一耳朵, 也好学习学习. 在这儿
混着不就是为了经常学习学习么?
【在 t****n 的大作中提到】 : 大半夜的,这么大脾气干吗?懂就是懂,不懂就是不懂。 : 不懂装懂,和懂装不懂,都是不对的,你说呢?
|
t****n 发帖数: 324 | 39 Xentar解释得很清楚了,其他发言反对楼主较真的人显然都没到他的程度,但是应该能看得懂Xentar的解释。
就事论事多好,你老何必呢?
其实搞技术,
一等的是有本事,没脾气;
二等的是有本事,有脾气,但本事不如一等的;
三等的是没本事,有脾气。
你老离一等很近了。
【在 t****t 的大作中提到】 : 你说得对啊, 所以我不是请你解释给他听么. 我顺便听一耳朵, 也好学习学习. 在这儿 : 混着不就是为了经常学习学习么?
|
t****t 发帖数: 6806 | 40 这个楼里最不就事论事的大概就是阁下您了.
能看得懂Xentar的解释。
【在 t****n 的大作中提到】 : Xentar解释得很清楚了,其他发言反对楼主较真的人显然都没到他的程度,但是应该能看得懂Xentar的解释。 : 就事论事多好,你老何必呢? : 其实搞技术, : 一等的是有本事,没脾气; : 二等的是有本事,有脾气,但本事不如一等的; : 三等的是没本事,有脾气。 : 你老离一等很近了。
|
|
|
t****n 发帖数: 324 | 41 Xentar解释完后,其他的解释都是画蛇添足了。至于其他对楼主的教训就完全都是负面了。我只不过看不惯你们这种态度。
如果你的意思是说自己说的那些还能跟就事论事占到点边的话,当我啥也没说好了。
【在 t****t 的大作中提到】 : 这个楼里最不就事论事的大概就是阁下您了. : : 能看得懂Xentar的解释。
|
t****t 发帖数: 6806 | 42 ...那我就只好当你啥也没说了.
面了。我只不过看不惯你们这种态度。
【在 t****n 的大作中提到】 : Xentar解释完后,其他的解释都是画蛇添足了。至于其他对楼主的教训就完全都是负面了。我只不过看不惯你们这种态度。 : 如果你的意思是说自己说的那些还能跟就事论事占到点边的话,当我啥也没说好了。
|
t*****o 发帖数: 4919 | 43 爬这个楼爬得快晕了, 编程的版都能唐成这样。
【在 b***i 的大作中提到】 : 这个问题和组里面自己定的风格还是有很大区别的。楼主问的类似于,我在15街闯红灯 : 每次都没事,在14街就不行,就被摄像头拍下来了,拿了罚单,这是为什么? : 大伙回答,两个街的摄像由不同的警察局审查。但是不应该研究这个问题,不闯红灯就行 : 了。而且,可以在不知道两个街由不同警察管理的情况下,只要不闯红灯,就可以完成 : 送饭的任务。 : 哪些方向可以研究呢?如果你没闯红灯却被误判了,就类似于编译器的错误了,这种情 : 况下是值得研究的。很多单片机的编译器都有错误,你了解了对工作是有好处的。但是 : ,如果编译器没有问题,写了错误的代码结果却没有太离谱,那只不过是运气,是没有 : 必要纠缠的。
|
r****y 发帖数: 26819 | 44 教得很耐心啊,完全是被迫唐。。。
【在 t*****o 的大作中提到】 : 爬这个楼爬得快晕了, 编程的版都能唐成这样。
|