不同计算机运行同一段C代码结果不一致的问题求助
为什么realloc后指针地址在不同机器上表现不一致?
先看看你提供的代码:
#include <stdlib.h> #include <stdio.h> void red(int *); int main() { int *wsk,i; wsk = (int*)malloc(10*sizeof(int)); for(i=0;i<10;i++) { wsk[i]=i+100; printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } printf("\n\n"); red(wsk); printf("\n\n"); for(i=0;i<11;i++) { printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } free(wsk); return 0; } void red(int* wsk) { int i; wsk = realloc(wsk,11*sizeof(int)); for(i=0;i<11;i++) { printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } }
你遇到的问题本质是C语言的参数值传递特性导致的,不同机器的内存分配策略放大了这个问题:
- 说白了,你把
main里的wsk传给red函数时,传的是这个指针的副本。red函数里对wsk的修改只会作用在这个副本上,完全不会影响main里的原始指针。 realloc的行为分两种情况:如果当前内存块后面有足够空间扩容,它会直接在原地址调整大小,返回原指针——这就是学校机器上出现的情况,所以red里的指针和main里的看起来一致,后续访问也没出问题;但如果原地址后面空间不够,realloc会分配一块新内存、拷贝旧数据、释放旧内存,这时候red里的wsk会指向新地址,但main里的指针还停在旧地址上,这就是你机器上出现的情况:后续main里循环访问11个元素时,越界访问了已经被释放的旧内存,就出现了乱码。
要解决这个问题,有两种靠谱的方式:
方式1:让red函数返回新的指针
修改red函数的返回值类型,把realloc后的指针返回给main:
#include <stdlib.h> #include <stdio.h> int* red(int *); // 修改函数声明 int main() { int *wsk,i; wsk = (int*)malloc(10*sizeof(int)); if (wsk == NULL) { // 检查malloc是否失败 fprintf(stderr, "malloc failed\n"); return 1; } for(i=0;i<10;i++) { wsk[i]=i+100; printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } printf("\n\n"); wsk = red(wsk); // 接收返回的新指针 if (wsk == NULL) { // 检查realloc是否失败 fprintf(stderr, "realloc failed\n"); return 1; } printf("\n\n"); for(i=0;i<11;i++) { printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } free(wsk); return 0; } int* red(int* wsk) { int i; wsk = realloc(wsk,11*sizeof(int)); if (wsk == NULL) { // 检查realloc失败 return NULL; } for(i=0;i<11;i++) { printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } return wsk; // 返回新指针 }
方式2:传递二级指针(指针的指针)
通过传递指针的地址,让red函数直接修改main里的原始指针:
#include <stdlib.h> #include <stdio.h> void red(int **); // 修改函数声明为二级指针 int main() { int *wsk,i; wsk = (int*)malloc(10*sizeof(int)); if (wsk == NULL) { // 检查malloc是否失败 fprintf(stderr, "malloc failed\n"); return 1; } for(i=0;i<10;i++) { wsk[i]=i+100; printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } printf("\n\n"); red(&wsk); // 传指针的地址 printf("\n\n"); for(i=0;i<11;i++) { printf("value: %d num pointer:%p \n",wsk[i],wsk+i); } free(wsk); return 0; } void red(int** wsk) { int i; *wsk = realloc(*wsk,11*sizeof(int)); // 修改原始指针的值 if (*wsk == NULL) { // 检查realloc失败 fprintf(stderr, "realloc failed\n"); return; } for(i=0;i<11;i++) { printf("value: %d num pointer:%p \n",(*wsk)[i],(*wsk)+i); // 访问指针指向的数组 } }
另外要记住:永远要检查malloc和realloc的返回值,如果内存分配失败,它们会返回NULL,不检查的话很容易导致程序崩溃。
内容的提问来源于stack exchange,提问作者aerodynamic96
相关产品推荐
相关产品推荐

