C语言中以指针地址计算为循环条件的异常问题排查
C语言指针代码运行异常的原因分析
你提供的代码存在多个概念错误,直接导致运行异常,下面逐一拆解问题:
原始代码
#include <stdio.h> #include <stdlib.h> // 原代码遗漏该头文件,`exit`和`malloc`依赖它 int main() { int var1 = 7; int* ptr1 = &var1; int* ptrHold = ptr1; int memo = 0; ptr1 = (int*)malloc(7*sizeof(int)); if(ptr1==NULL){ printf("Memory couldn't be allocated..."); exit(0); } else{ printf("Memory allocated for ptr1 = %d\n",7*sizeof(int)); printf("%d\n",(*(&ptr1+1)-ptr1)); for(int i=0;memo<=(*(&ptr1+1)-ptr1)/sizeof(int);i++){ *ptr1=i; memo += (int)(sizeof(int)); ptr1++; } } ptr1 = ptrHold; for(int i=0;i<5;i++){ printf("%d\n",ptr1[i]); } free(ptr1); return 0; }
核心错误点
1. 错误通过*(&ptr1+1)-ptr1获取malloc内存大小
&ptr1是指向栈上指针变量ptr1的指针(类型为int**),&ptr1+1指向的是栈上ptr1变量之后的内存位置,和你用malloc在堆上分配的内存完全无关。这个计算出的差值是栈上相邻变量的地址差,属于无意义的垃圾值,根本不是你要的堆内存大小。
2. 循环条件逻辑完全混乱
你的循环条件memo<=(*(&ptr1+1)-ptr1)/sizeof(int)不成立:memo累加的是sizeof(int)(通常为4),而右边是垃圾值除以4,两者没有对应关系,会导致循环次数完全不可控,要么少赋值,要么越界访问堆内存,甚至破坏栈上的数据。
3. 错误释放栈内存
最后你把ptr1重新赋值为ptrHold(指向栈上的var1),然后调用free(ptr1)——free只能释放malloc/calloc/realloc在堆上分配的内存,释放栈内存属于未定义行为,会直接导致程序崩溃。
修正后的代码(符合预期输出)
#include <stdio.h> #include <stdlib.h> int main() { int var1 = 7; int* ptr1 = &var1; int* ptrHold = NULL; // 初始化为NULL,避免后续混淆 int allocCount = 7; // 直接记录分配的int数量,这是你已知的参数 ptr1 = (int*)malloc(allocCount * sizeof(int)); ptrHold = ptr1; // 保存堆内存的起始地址,而非栈变量地址 if(ptr1 == NULL){ printf("Memory couldn't be allocated..."); exit(0); } else{ printf("Memory allocated for ptr1 = %d\n", allocCount * sizeof(int)); // 直接用已知的分配数量控制循环,这是正确做法 for(int i=0; i < allocCount; i++){ ptr1[i] = i; } } // 用保存的堆起始地址遍历输出 for(int i=0; i<5; i++){ printf("%d\n", ptrHold[i]); } free(ptrHold); // 释放堆内存,符合`free`的使用要求 return 0; }
修正说明
- 新增
allocCount变量记录malloc分配的int数量,直接用这个值控制循环——malloc分配的内存大小无法通过指针本身获取,必须自行记录。 ptrHold改为保存堆内存的起始地址,避免和栈变量地址混淆。- 移除无意义的
*(&ptr1+1)-ptr1计算,改用数组下标ptr1[i]赋值,逻辑更清晰。 - 最后释放堆内存的起始地址
ptrHold,符合内存管理规范。
预期输出
Memory allocated for ptr1 = 28 0 1 2 3 4
内容的提问来源于stack exchange,提问作者daran
相关产品推荐
相关产品推荐

