欢迎加入西电微软俱乐部招新群 588166170,做出福利题,免技术部第一次面试且赠送“福利”海报或小礼品~~~~
Xidian Online Judge WebBoard
[ New Thread ]
MainBoard >> 关于未定义行为(科普)
xry111 @ 2015-05-19 19:46:26
[ Quote ] [ Edit ] [ Delete ] 1#
0. 什么是未定义行为(Undefined Behaviour)
在计算机程序设计中,未定义行为是指行为不可预测的计算机代码。这是一些编程语言的一些特点,最有名的是在C语言中。在这些语言中,为了简化标准,并给予实现一定的灵活性,标准特别地规定某些操作的结果是未定义的,这意味着程序员不能预测会发生什么事。
特别地,标准从未要求编译器判断未定义行为。因此,如果程序调用未定义行为,可能会成功编译,甚至一开始运行时没有错误,只会在另一个系统上,甚至是在另一个日期运行失败。当一个未定义行为的实例发生时,正如语言标准所说,“什么事情都可能发生”,也许什么都没有发生。
xry111 @ 2015-05-19 19:53:07
[ Quote ] [ Edit ] [ Delete ] 2#
1. 未定义行为的危害
和未指定行为(Unspecified Behaviour)不同,未定义行为强调基于不可移植或错误的程序构造,或使用错误的数据。一个符合标准的实现可以在假定未定义行为永不发生(除了显式使用不严格遵循标准的扩展)的基础上进行优化,可能导致原本存在未定义行为(例如有符号数溢出)的程序经过优化后显示出更明显的错误(例如死循环)。因此,未定义行为一般被视为bug。
在西电,由于C/C++的教学水平较低,特别是极个别老师不懂得未定义行为,经常强行断言某个未定义行为的行为,并以此折磨学生。这导致学生在编程中滥用未定义行为,带来很多看上去莫名其妙的WA、RE甚至TLE。因此,有必要强调在编程中避免未定义行为。
xry111 @ 2015-05-19 20:34:14
[ Quote ] [ Edit ] [ Delete ] 3#
2. C/C++中常见的未定义行为
2.0 指针
(1)试图对NULL指针求值,例如
int *p = NULL;
printf("%d\n",*p);
(2)试图对new运算符分配的指向大小为0的内存块的指针求值。例如:
int *p = new int[0];
printf("%d\n",p[0]);
(3)试图对指向生命周期已经结束的对象的指针求值。例如:
int *foo(){int x = 5; return &x;}
int main(){int *p=foo(); printf("%d\n",*p);}
(4)试图对未初始化的指针求值。例如:
int *p;
printf("%d\n",*p);
(5)试图对地址运算产生的超过数组边界的指针求值。例如:
const char *str = "Li Lun AC Suan Ge Pi!"
putchar(str[100]); //Equivlent to *(str+100).
(6)试图将指针转化成不兼容的类型。例如:
int a = 123;
char *p = &a;
putchar(*p);
(7)使用memcpy,源区域和目标区域发生重合。

2.1 缓冲区溢出
栈溢出和堆溢出的行为是不确定的。

2.2 整数溢出
(1)有符号整数溢出。例如:
for(int i = INT_MAX; i>=0; i++);
可能陷入死循环。如果要运用整数溢出的结果(比如字符串hash),使用无符号整数。
(2)计算数学上未定义的结果,例如除以0。
(3)左移负数位,例如1<<(-10)。
(4)左移超过整数位数,例如
int64_t i = 1; i<<=72;

2.3 类型,类型转换,常量
(1)把数值类型转成另一个数值类型,导致原来的值无法表示。例如
double x = 1.0/0.0-1.0/0.0; //x is NAN
int t = x;
(2)使用没有初始化的变量。
(3)试图修改常量(包括字符串常量)的值。例如:
char *t = "li lun AC suan ge pi!"
t[0] = 'L';

2.4 函数与模板
(1)在非void类型的函数中不返回值。
(2)在模板的实例化中发生无限递归。
(3)采用不符合参数表的参数调用函数。

2.5 面向对象编程
(1)对静态/全局对象调用析构函数。
(2)对部分重叠的对象调用拷贝构造函数。
(3)在函数内部的静态局部变量初始化中重入此函数。
(4)在构造、析构函数中调用纯虚函数。
(5)访问尚未构造或已经析构的对象。
xry111 @ 2015-05-19 20:39:16
[ Quote ] [ Edit ] [ Delete ] 4#
3. 如何避免未定义行为
(1)养成良好的编程习惯。
(2)编译时使用警告选项。
mathhater @ 2015-05-22 18:41:39
[ Quote ] [ Edit ] [ Delete ] 5#
沙发~~~~~~膜拜习大大~~~
[Top] [Previous Page] [Next Page]
Anything about the Problems, Please Contact Admin:admin
All Copyright Reserved 2010-2014 Xidian ACM Online Judge TEAM
GPL2.0 2003-2014 HUSTOJ Project TEAM