2019独角兽企业重金招聘Python工程师标准>>>
1. 正确情况
void func()
{
char *pChar = new char;
//赋值
pChar[0] = 'a';
}
2. 错误情况,但程序不一定会崩溃
void func()
{
char *pChar = new char;
// 赋值
pChar[0] = 'a';
pChar[1] = 'b';
}
3. 错误情况,程序崩溃可能性大于(2)
void func()
{
char *pChar = new char;
// 赋值
pChar[0] = 'a';
pChar[1] = 'b';
//......
pChar[1023] = 'c';
pChar[1024] = 'd';
}
总结: 造成上诉情况的主要原因是:
一. C/C++的内存分为5大区
栈区,堆区,符号常量区,全局/静态区,程序代码区
二. 现在计算机是多任务的,也就是说内存中同时存在多个进程,操作系统为每个进程都分配了一定的内存空间
三. 每个进程对自己所拥有的内存具有访问(读写)权限
四. 除了堆区外的空间都是在编译时就确定的,所以无法改变,只有堆区是可以动态扩充的
五. 当指针访问到了不属于当前进程所拥有的内存时,就会发生中断终止程序(程序崩毁)
六. char *pChar = new char; 是在当前进程的堆区中开辟一小块内存(大小为1Byte),pChar拥有对这块(1Byte)内存操作的权利,而实际上,pChar拥有访问当前进程整个堆区的权利
七. 理论上每个进程的堆区大小为2-3GByte,但初始大小却可能只有几十KByte左右
八. 所以上诉程序实际上是对自己的堆区内存进行赋值操作(毫无意义),又由于程序在内存中的分布通常是不完全连续的,所以程序的指针越界是非常危险的行为(导致程序崩溃的主要原因)
九. 同理
char ch, *pChar = &ch;
此时 pChar 拥有对当前进程的栈区进行访问的权利,但越界操作可能会访问到其它进程的空间而导致程序崩溃
同时,栈区内存大小 通常小于 堆区的初始内存大小
所以在堆区 pChar[1024] 可能不会导致程序崩溃
但在栈区中 pChar[512] 可能就会导致程序崩溃
十. 当你程序中使用指针的时候,一定要牢记越界检查,因为即便程序在运行时没有崩溃也并不一定代表指针就一定没有越界。