免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 14856 | 回复: 68
打印 上一主题 下一主题

[C] 关于UB的问题 [复制链接]

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-01-14 20:45 |只看该作者 |倒序浏览
       最近上CU论坛的C/C++板块,很多话题都是围绕着UB的,从它的英文名Undefined Behavior看来,它就是未定义的行为。
       未定义的行为,编译器或者IDE应该会有相应的手段处理,要么直接报错,或者有警告提示,要么编译器自行定义过相应的行为,否则,如果真心不知道该怎么办,那编译器是怎么处理的?
       如果代码中出现未定义行为,会出现什么后果呢?最近论坛里吵得特别凶,我十分好奇这个问题,请高手给出具体一点儿的解释。
       而且我听说,合理的C代码不应该有类似这种a+=a-=a*a;还需要分析好半天的代码。是不是如果代码里面只要没有这种不合理的代码,就不会有UB呢?是不是遵循友好代码原则的代码就没有UB问题呢?
       谢谢各位高手赐教,但不希望这个帖子成为吵架帖,谢谢!

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
2 [报告]
发表于 2013-01-14 20:55 |只看该作者

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
3 [报告]
发表于 2013-01-14 21:03 |只看该作者
@群雄逐鹿中原很抱歉,刚才忘了问你了

论坛徽章:
0
4 [报告]
发表于 2013-01-14 21:10 |只看该作者
我的粗浅理解:

未定义行为的「未定义」指的是在标准中没有对行为作出强制规定。实际落实到某一个编译器的具体实现时,编译器自己选择一个认为合理的行为作为准则,所以在具体编译器这一层面上讲,是有明确定义的,不是说今天编译出来是这个结果、明天是那个结果 ╮(╯▽╰)╭ 但编译器之间可能有不同的行为。

代码中出现未定义行为的危害首当其冲的应该是可移植性。

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
5 [报告]
发表于 2013-01-14 21:21 |只看该作者
回复 4# timothyqiu


    额,我百度了一下也有类似说法,也就是UB只影响代码的可移植性,如果程序是针对平台的,就不用考虑这个问题了。
   还有一个问题,很多地方都说要编写友好代码,就是便于别人修改的代码,是不是遵循这一原则写的代码就没有UB问题

论坛徽章:
0
6 [报告]
发表于 2013-01-14 22:01 |只看该作者
方兆国 发表于 2013-01-14 21:21
回复 4# timothyqiu

还有一个问题,很多地方都说要编写友好代码,就是便于别人修改的代码,是不是遵循这一原则写的代码就没有UB问题


友好的代码应该能规避一些未定义行为问题(比如你举的例子),但是肯定不能规避所有的未定义行为。比如
  1. int x;
  2. ... 对 x 初始化 ...
  3. some_func_require_shifted_x(x << 1);
复制代码
看着够友好了,但依旧存在未定义的隐患(x 的最高非符号位为 1 时)。

我想,规避的办法除了靠错误累积经验,也许就只能在有闲情逸致时看标准里对未定义行为描述了,比如 C99 标准后面就附有所有的未定义行为列表。

p.s. 还有一个 Unspecified Behavior 其实和 Undefined Behavior 大同小异,前者是给出了若干个可选行为没有指定,后者是完全随意发挥……(所以基本看不到有人用 UB 这个缩写)

论坛徽章:
4
CU大牛徽章
日期:2013-03-13 15:29:07CU大牛徽章
日期:2013-03-13 15:29:49CU大牛徽章
日期:2013-03-13 15:30:192015年迎新春徽章
日期:2015-03-04 09:57:09
7 [报告]
发表于 2013-01-14 22:17 |只看该作者
如果你有洁癖就不会容忍那样的语句存在。

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
8 [报告]
发表于 2013-01-14 22:27 |只看该作者
回复 6# timothyqiu


    额,我也是在论坛上看到的UB,以前可能见过,没注意过
刚刚测试了一下,编译器确实有这种警告,有警告的话,就没有多少关系了
  1. int main(int argc, char *argv[])
  2. {
  3.         int a = 5;
  4.         a += a -= a * a;
  5.         printf("%d", a);
  6.         return 0;
  7. }
复制代码
下面是Eclipse+MinGW的构建结果
  1. 22:24:45 **** Rebuild of configuration Debug for project file_2.2.3 ****
  2. Info: Internal Builder is used for build
  3. gcc -O0 -g3 -Wall -c -fmessage-length=0 -o "bin\\file_2.2.3.o" "..\\bin\\file_2.2.3.c"
  4. ..\bin\file_2.2.3.c: In function 'main':
  5. ..\bin\file_2.2.3.c:42:4: warning: operation on 'a' may be undefined [-Wsequence-point]
  6. ..\bin\file_2.2.3.c:42:4: warning: operation on 'a' may be undefined [-Wsequence-point]
  7. gcc -o file_2.2.3.exe "bin\\file_2.2.3.o"

  8. 22:24:46 Build Finished (took 1s.575ms)

复制代码

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
9 [报告]
发表于 2013-01-14 22:27 |只看该作者
甚至同一个编译器的版本改变,都可能导致未定义行为的改变。除非你确定你绝不会升级编译器什么的。

有些未定义行为很难检测,有一些甚至只有在运行时才会偶然出现,比如int类型的溢出这种UB——你怎么在编译的时候就判断是否会溢出?

gcc会尽量给出UB的提示(比如你给出的那个表达式),但是也有判断不出来的。

论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-09-18 15:15:15CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:31CU大牛徽章
日期:2013-05-20 10:46:25CU大牛徽章
日期:2013-05-20 10:46:18CU大牛徽章
日期:2013-04-17 11:19:51CU大牛徽章
日期:2013-04-17 11:19:42CU大牛徽章
日期:2013-04-17 11:19:37CU大牛徽章
日期:2013-04-17 11:19:32CU大牛徽章
日期:2013-04-17 11:19:28
10 [报告]
发表于 2013-01-14 22:28 |只看该作者
回复 7# dooros


    额,这样,我的代码习惯是定义的时候立即初始化,尽量用短代码,感觉还好
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP