C++中的未定义行为(undefined behavior)
来源:互联网 发布:popsub字幕制作软件 编辑:程序博客网 时间:2024/05/18 13:27
<< BACK
new[],能否用delete而不是delete[]释放? 因为明确说了不是类对象,所以这里可以不考虑数组对象析构时的错误,那么这样做可不可以呢?
一种声音是:严格遵守C++标准,保持好习惯;另一种声音:不要生搬经典,要自己实践才知道。
为了弄清这个问题,不得不引入一个词“未定义行为”(undefined behavior)。
In computer science, undefined behavior is a feature of some programming languages — most famously C. In these languages, to simplify the specification and allow some flexibility in implementation, the specification leaves the results of certain operations specifically undefined.
——Wikipedia (http://en.wikipedia.org/wiki/Undefined_behavior)
对于未定义行为,C++标准没有明确规定编译器们应该怎么做,那么执行的结果就是不可预料的。对于上面那个new[]完用delete释放的问题,编译器会做什么呢?不知道,因为C++标准没规定他做什么。夸张点说,即使是编译出来的程序把硬盘格式化了,也不能说这个编译器是个不符合C++标准的——它依然可能是一个完全符合C++标准的优秀编译器。
下面就用实际例子来试试吧。
int main(int argc, char* argv[])
{
while (1)
{
int* p=new int[1024*1024];
delete p; //没有用delete[] p;
}
return 0;
}
上面这段程序在VS下编译,执行了很久,从任务管理器里没发现有什么异常。不过这样就算是没问题了么?
先换个问题看看,很多C语言启蒙教材里的程序里main()的返回值是void型的:
void main()
{
}
这样的程序,大家很习惯了,因为在微软的编译器里,这样是完全可以的。不过有没有试过在LINUX下GCC编译器或者更多其他编译器里试过编译一下呢?很多是会报错的!其实,ANSI C明确规定了main()就是返回int的,void main()的用法是错误的。如此来说,在VS下能编译并正常运行的,就一定是正确的么?
上面只是个不符合标准的例子,而更多问题,则出现在 undefined behavior 上。正是因为C++标准中没有定义它,编译器没有责任说必须怎么做,[不同编译器] 或者 [同一编译器的不同版本] 或者 [同一编辑器同一版本在使用不同编译选项时] 都可能会有不同执行结果。不相信么?那么事实说话,看个程序吧。
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int x=0;
x=(x++)+(++x)+(x++)+(++x);
cout<<x<<endl;
return 0;
}
VC 6.0下编译,Debug版本输出7,release版本呢?却是10!为什么呢?其他编译器也许会有更多不同答案。
另一个程序:
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int x=1;
x=(x++ * ++x + x-- * --x);
cout<<x<<endl;
return 0;
}
VC 6.0下编译Debug版本输出5,VS 2003下Debug版本输出2。
同时微软的编译器出来的结果都各种各样,就更不用说其他公司更多的编译器了。肯定还有更多答案,不过结果本身没有意义,C++标准没有定义这种行为,对于这种undefined behavior,编译器爱怎么做都行,而我们能做的,是避免这种情况出现。“有实力的C++程序员能以最佳状态避开未定义行为。”
回到最初new[]与delete配对的问题。C++标准里规定了new\delete要配对、new[]\delete[]要配对,并没有说new[]与delete配对之后会做些什么,也就是一种未定义行为,会发生什么无法知道。即使当前某个编译器编译是正确的,至于以后的某个版本是否仍然正确也无法知道。何况C++中可以对new\delete、new[]\delete[]重新定义,谁能保证做了些什么,会有什么不同呢?
所以最保险、最规范的做法还是,严格遵守C++标准,坚决避免一切undefined behavior。
- C++中的未定义行为(undefined behavior)
- C++中的未定义行为(undefined behavior)
- 浅谈未定义行为(Undefined behavior)
- C语言(undefined behavior)未定义-序
- C语言undefined behaviour未定义行为
- C语言undefined behaviour未定义行为
- C语言undefined behaviour未定义行为
- C语言undefined behaviour未定义行为
- C语言undefined behaviour未定义行为
- C语言undefined behaviour未定义行为
- C语言中的未定义行为
- c语言中的未定义行为
- 矫情的C++——不明确行为(undefined behavior)
- C语言的未定义行为(undefined behaviour)
- C/C++语言中的未定义行为
- C++中的未定义行为
- C语言未定义行为
- 编程中的“未定义行为”问题
- 指针加减操作
- java * 第八周* 任务【一】继承的练习
- 关于修改Android开机画面的方法和问题(rle制作工具,raw制作工具,很实用)
- 计算定期还款额度
- People
- C++中的未定义行为(undefined behavior)
- 狗狗40题
- 说了N多年都说不清的结构体对齐问题
- Java对象的XML序列化和反序列化 - (1)
- 交叉引用和extern的使用
- java * 第八周* 任务【二】接口的练习
- 一些在Android中的小设置~~~持续添加
- 10款出色的NoSQL数据库
- Java Sax解析xml