悬空指针和未定义的行为问题:已在XXXXX.exe 中执行断点指令(__debugbreak()语句或类似调用)。

文章讲述了在处理二叉树链式转顺序存储过程中,使用realloc进行内存扩容时遇到的悬空指针问题,即在递归函数中,由于地址传递导致的内存释放后的无效访问,引发的未定义行为。解决方法是将指针改为引用以确保指向有效内存。
摘要由CSDN通过智能技术生成
     
在如下二叉树链式转顺序存储函数中,对顺序表a扩容(char* aa = (char*)realloc(a, size*sizeof(char));)时会报:“已在 BinaryTree.exe 中执行断点指令(__debugbreak()语句或类似调用)。”
函数代码如下:
char* a = (char*)malloc(MAXSQLIST * sizeof(char));
int Aflag = 0,maxflag= MAXSQLIST;

void list_prueue(Bitree* T, char* a, int Aflag, int& maxflag) {
if (Aflag > maxflag) {
int size = maxflag + LONGSIZE;
char* aa = (char*)realloc(a, size*sizeof(char));
if (aa)
{
a = aa;
maxflag = maxflag + LONGSIZE;
}
else return;
}
if (T) {
a[Aflag] = T->data;
list_prueue(T->left, a, Aflag*2+1, maxflag);
list_prueue(T->right, a, Aflag*2+2, maxflag);
}
else { a[Aflag] = '#';  }
}



调试分析后,我发现是第二次扩容时报错。同时我观察了时期的a与aa的地址值。



我认为是“共享内存引发的悬空指针和未定义的行为问题” void list_prueue(Bitree* T, char* a, int Aflag, int& maxflag)是一个递归函数,各个递归共享顺序表a,但这里出现了一个realloc特殊情况(异地扩容)下引发的问题,在QQ日志中我介绍过realloc函数使用规则,第一次扩容时顺序表a所在的内存空间后面没有足够的连续空间扩大a指向的地址,这时空间不够,先另外找一块满足指定size的大小连续空间并分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来a所指内存区域(000001614DCAC3F0)(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址(000001614DCA2A10)。


也就是第一次扩容,a原来的所指向的连续内存已被释放,而本函数char* a 是传递的地址,这就意味着其他正在递归的函数中a指向了一个被释放的内存区域,此时指针a指向的就是无效内存,a变成了“悬空指针”, 这时候如果再次访问这个指针,就会导致不可预测的结果,可能会引发程序崩溃或者数据损坏等问题。

第二次扩容时,realloc再次访问这个指针(000001614DCAC3F0),它就傻眼了(?-?)当a为悬空指针时,realloc函数的行为是未定义的。这意味着它可能会导致程序崩溃或产生其他不可预测的结果。因此,在使用realloc函数时,应该始终确保a指向已分配的内存块。

于是我把char* a改成char* &a;指针引用,这就可以了!

注:未定义行为(undefined behavior)”是在C语言标准中定义的。

标准原文为:behavior, upon use of a nonportable or erroneous program construct or of erroneous data,for which this International Standard imposes no requirements

译文为:在使用不可移植的或错误的程序结构或错误的数据时的行为,本国际标准对此没有要求

简而言之,未定义行为就是指程序执行时的行为是无法预知的。

例如,缓冲区访问越界就是一种未定义行为。当发生该行为时,我们无法确定越界访问内存的真实地址和内容,因此也就无法预知该行为会对程序执行产生的影响

关于realloc()悬空指针和未定义的行为可详见关于C#:realloc()悬空指针和未定义的行为 | 码农家园

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值