C/C++ new delete 。有个奇怪的问题。 编译环境vs2010
int_tmain(intargc,_TCHAR*argv[]){int*newINT=newint[2];//如果我强制给未定义的*(newINT+2)赋值,按下F5的...
int _tmain(int argc, _TCHAR* argv[])
{
int *newINT = new int[2];
//如果我强制给未定义的*(newINT+2)赋值,按下F5的时候界面一直停在哪儿不主动退出(属于异常但不报错)
*(newINT+2) = 5;
//如果我强制给未定义的*(newINT+3)赋值,按下F5的时候,报错!
// *(newINT+3) = 5;
delete [] newINT;//整个程序如果注释掉delete语句编译器无异常不报错
return 0;
}
-----------------------------------------------------------------------------------------------------------------
亲们,我在此声明我知道指针和不能越界等等的重要性。在这里我只是想探究产生这种现象的深沉次原因。
-----------------------------------------------------------------------------------------------------------------
最先我是好奇int newINT = new int[0]时会发生什么事。最后在C++ Primer上找到
“用 new 动态创建长度为 0 的数组时,new 返回有效的非零指针。该指针与 new 返回的其他指针不同,不能进行解引用操作,因为它毕竟没有指向任何元素。而允许的操作包括:比较运算,因此该指针能在循环中使用;在该指针上加(减)0;或者减去本身,得 0 值。”
但是我在调试过程中发现当执行*newINT = 5;时。delete时就出现异常了。
在网上也查到过ch = (char*)malloc(0);如果此时*ch = ‘a’的话在free时也会出问题。 展开
{
int *newINT = new int[2];
//如果我强制给未定义的*(newINT+2)赋值,按下F5的时候界面一直停在哪儿不主动退出(属于异常但不报错)
*(newINT+2) = 5;
//如果我强制给未定义的*(newINT+3)赋值,按下F5的时候,报错!
// *(newINT+3) = 5;
delete [] newINT;//整个程序如果注释掉delete语句编译器无异常不报错
return 0;
}
-----------------------------------------------------------------------------------------------------------------
亲们,我在此声明我知道指针和不能越界等等的重要性。在这里我只是想探究产生这种现象的深沉次原因。
-----------------------------------------------------------------------------------------------------------------
最先我是好奇int newINT = new int[0]时会发生什么事。最后在C++ Primer上找到
“用 new 动态创建长度为 0 的数组时,new 返回有效的非零指针。该指针与 new 返回的其他指针不同,不能进行解引用操作,因为它毕竟没有指向任何元素。而允许的操作包括:比较运算,因此该指针能在循环中使用;在该指针上加(减)0;或者减去本身,得 0 值。”
但是我在调试过程中发现当执行*newINT = 5;时。delete时就出现异常了。
在网上也查到过ch = (char*)malloc(0);如果此时*ch = ‘a’的话在free时也会出问题。 展开
7个回答
展开全部
这个可以这样说,CRT 的内存管理机制,如果你越界读写了 CRT 管理的内存区,delete 或者 free 时都会报错,不管是上越界还是下越界 。
因为由 CRT 管理的内存区,是有着自己独特的内存分布格式的,比如你 new char[ 10 ],那么内存布局大概像这样子 :
----------------------------------------------------------------------------
| CRT 检查区 | char[ 10 ] 区 | CRT 检查区 |
----------------------------------------------------------------------------
至于报错,并不是说越界访问就一定会有风险,而是在 Debug 模式下给开发者的警告
Release 模式下会移除 CRT 检查区,剩下用户内存区,此时,如果用户非常明确地掌握内存布局的话,那么对于一些合法的越界访问是可以的 。
因为由 CRT 管理的内存区,是有着自己独特的内存分布格式的,比如你 new char[ 10 ],那么内存布局大概像这样子 :
----------------------------------------------------------------------------
| CRT 检查区 | char[ 10 ] 区 | CRT 检查区 |
----------------------------------------------------------------------------
至于报错,并不是说越界访问就一定会有风险,而是在 Debug 模式下给开发者的警告
Release 模式下会移除 CRT 检查区,剩下用户内存区,此时,如果用户非常明确地掌握内存布局的话,那么对于一些合法的越界访问是可以的 。
追问
啊哈!我也是这么猜测的,但是什么叫CRT 的内存管理机制啊我在网上没搜索到啊。实际上我就想了解我出这些错内存中发生了什么事情。
追答
你的错误就是因为越界访问了由 CRT 管理的内存区咯
你分配了一个 int[ 2 ] 数组
但是你却访问了 int[ 3 ] 这个位置,说明你上越界了
delete 的时候就被检测到了,所以 delete 的时候程序崩溃了
展开全部
一、关于程序
int _tmain(int argc, _TCHAR* argv[])
{
int *newINT = new int[2]; //分配两个整型数据空间。
*(newINT+2) = 5; //这里不出错,属于你运气好,呵呵,+0 +1都可以,+2越界了!
// *(newINT+3) = 5; 这个不说了,当然也是越界了,出错就对了,运气好时,也可能不出错。
delete [] newINT;//当你的程序退出时,系统会自动释放你所有的资源,包括你的指针申请空间,因此,你注释掉这句也不会有任何警告或错误。
return 0;
}
什么是运气好?就是你所占用的非自己的内存空间,一对别人没有影响,二没有任何人去使用该 空间,好比“擦边球”。
二、int newINT = new int[0]时会发生什么事。
先不论书是怎么说的,单看这个操作,分配0空间,可以理解为没有分配空间。当你向这个指针地址中放数据时,因为它没有空间,所以,数据会存储到别人的空间中去,就会产生越界。不出错,只能说是你运气好,不代表没有错误。(BUG就是这样来的)
三、delete 和 free是相类似的操作,一个是C++专属的,一个是通用的。当去释放一个没有分配空间的指针时,系统一定会出错的。(当然,这也和这两个函数命令的设计有关)
四、关于书上的话:
“用 new 动态创建长度为 0 的数组时,new 返回有效的非零指针。(这里不知道为什么要这样安排,按理应该返回空指针NULL才合理,不知道是不是编译系统BUG)
该指针与 new 返回的其他指针不同,不能进行解引用操作(解引用就是delete,free的意思),因为它毕竟没有指向任何元素。(这个理由不知道是不是杜撰来的)
而允许的操作包括:
比较运算(什么比较?是指针内容的比较,还是指针的比较?如果是前者,能比较出来结果吗?它连内容都没有,如何去比较?如果是后者,它是NULL也可以啊),因此该指针能在循环中使用;
在该指针上加(减)0(这不是废话?);或者减去本身,得 0 值(也是废话)。”
int _tmain(int argc, _TCHAR* argv[])
{
int *newINT = new int[2]; //分配两个整型数据空间。
*(newINT+2) = 5; //这里不出错,属于你运气好,呵呵,+0 +1都可以,+2越界了!
// *(newINT+3) = 5; 这个不说了,当然也是越界了,出错就对了,运气好时,也可能不出错。
delete [] newINT;//当你的程序退出时,系统会自动释放你所有的资源,包括你的指针申请空间,因此,你注释掉这句也不会有任何警告或错误。
return 0;
}
什么是运气好?就是你所占用的非自己的内存空间,一对别人没有影响,二没有任何人去使用该 空间,好比“擦边球”。
二、int newINT = new int[0]时会发生什么事。
先不论书是怎么说的,单看这个操作,分配0空间,可以理解为没有分配空间。当你向这个指针地址中放数据时,因为它没有空间,所以,数据会存储到别人的空间中去,就会产生越界。不出错,只能说是你运气好,不代表没有错误。(BUG就是这样来的)
三、delete 和 free是相类似的操作,一个是C++专属的,一个是通用的。当去释放一个没有分配空间的指针时,系统一定会出错的。(当然,这也和这两个函数命令的设计有关)
四、关于书上的话:
“用 new 动态创建长度为 0 的数组时,new 返回有效的非零指针。(这里不知道为什么要这样安排,按理应该返回空指针NULL才合理,不知道是不是编译系统BUG)
该指针与 new 返回的其他指针不同,不能进行解引用操作(解引用就是delete,free的意思),因为它毕竟没有指向任何元素。(这个理由不知道是不是杜撰来的)
而允许的操作包括:
比较运算(什么比较?是指针内容的比较,还是指针的比较?如果是前者,能比较出来结果吗?它连内容都没有,如何去比较?如果是后者,它是NULL也可以啊),因此该指针能在循环中使用;
在该指针上加(减)0(这不是废话?);或者减去本身,得 0 值(也是废话)。”
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1,编译器能对代码的语法和语义出现的错误进行检查。它能保证编译和链接能够完成。
2,对于运行期间出现的错误,编译器是无法判定的。特别是逻辑、非法访问、运行权限等,这些是编译期间不能完全解决的。
*newINT = 5;时。delete操作,是在运行期间进行的,是对指针的操作,而指针是非法的。不出错的可能性极小。
3,指针是一把双刃剑。任何时候使用,都要很小心。能和引用的地方就不要用指针,除非一定要用。
2,对于运行期间出现的错误,编译器是无法判定的。特别是逻辑、非法访问、运行权限等,这些是编译期间不能完全解决的。
*newINT = 5;时。delete操作,是在运行期间进行的,是对指针的操作,而指针是非法的。不出错的可能性极小。
3,指针是一把双刃剑。任何时候使用,都要很小心。能和引用的地方就不要用指针,除非一定要用。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
我想我大概了解你想问的是什么。
首先看 int *newINT = new int[0] 时发生了什么, 分配给了指向int的指针 newINT长度为0的空间,这里是指newINT的分配的地址长度长度为0,所以不可以对它做解引用;但是由于对newINT已经成功地分配了地址(尽管地址长度为0),所以newINT本身是有意义的,因而也可以做一些操作,如比较运算。
从内存分配的角度来说newINT本身的指针结构已经分配了地址,是有效的,但是它指向的对象却是长度为零,无效的。我想编译器这么设计是为了完备性的考虑。
首先看 int *newINT = new int[0] 时发生了什么, 分配给了指向int的指针 newINT长度为0的空间,这里是指newINT的分配的地址长度长度为0,所以不可以对它做解引用;但是由于对newINT已经成功地分配了地址(尽管地址长度为0),所以newINT本身是有意义的,因而也可以做一些操作,如比较运算。
从内存分配的角度来说newINT本身的指针结构已经分配了地址,是有效的,但是它指向的对象却是长度为零,无效的。我想编译器这么设计是为了完备性的考虑。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
编译器只能尝试帮助你检测这种越界情况,不可能有非常统一的现象出来。在越界情况下,错误现象确实是不确定的,所以避免越界是很重要的
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询