C语言中用malloc处理多字符串正常,为何calloc无法实现?
双指针内存分配:calloc替代两次malloc失败的原因
首先,先明确你的场景:你写了一段用双指针处理两个字符串的代码,通过两次malloc(先分配指针数组,再为每个指针分配字符串缓冲区)能正常运行,但尝试用一行calloc替代这两步操作时却无法正常工作,想知道其中的原因。
你的原代码(格式化后)
#include <stdio.h> #include <stdlib.h> int main(){ int i=0; char **ptr=NULL; ptr =(char **) malloc(2*sizeof(char)); // 这里存在潜在问题,后面会说明 if(ptr==NULL){ printf("Memory not allocated!\n"); return -1; } for(i=0; i<2;i++){ ptr[i] = (char *)malloc(20*sizeof(char)); if(ptr[i]==NULL){ printf("Memory not allocated!\n"); return -1; } } for(i=0; i<2;i++) scanf("%s", ptr[i]); for(i=0; i<2; i++) printf("%s\n", ptr[i]); for(i=0; i<4; i++) printf("%c\n", ptr[0][i]); for(i=0; i<4; i++) printf("%c\n", ptr[1][i]); free(ptr[0]); free(ptr[1]); free(ptr); return 0; }
你尝试的calloc语句
ptr = (char **)calloc(2, sizeof(char)*20);
问题出在哪?
我们先拆解原代码的内存分配逻辑:
- 第一步
malloc(2*sizeof(char)):你想分配一个能存2个char*的指针数组(这里其实写错了,应该是2*sizeof(char*),因为ptr是char**,每个元素是指针类型,不是char类型!你的机器可能是32位系统,指针大小和char大小刚好巧合让这段代码暂时能跑,但这是个bug)。这部分内存是用来存储两个指向字符串缓冲区的指针。 - 第二步循环里的
malloc(20*sizeof(char)):为每个指针单独分配一块20字节的连续内存,作为字符串的存储缓冲区。
而你的calloc语句是直接分配了2*20=40字节的连续内存,然后强制转成char**。这时候问题来了:
char** ptr的语义是指向指针的指针,也就是说ptr应该指向一块存储指针的内存。但你的calloc分配的是40字节的普通字符内存,不是指针数组。- 当你尝试用
ptr[0]时,程序会把ptr指向的前sizeof(char*)个字节(比如4或8字节)当成一个指针地址,然后去访问这个“假指针”指向的内存——这显然是非法的,因为这部分内存本来是用来存字符串内容的,不是有效的内存地址,所以程序会崩溃或者出现不可预料的行为。
正确的calloc替代方式
如果你想用calloc实现原代码的效果,需要分两步,和原代码的逻辑一致:
// 第一步:分配存储2个char*的指针数组,calloc会自动初始化内存为0 ptr = (char **)calloc(2, sizeof(char*)); if(ptr==NULL){ printf("Memory not allocated!\n"); return -1; } // 第二步:为每个指针分配字符串缓冲区 for(i=0; i<2;i++){ ptr[i] = (char *)calloc(20, sizeof(char)); // calloc初始化0,更适合字符串存储 if(ptr[i]==NULL){ printf("Memory not allocated!\n"); return -1; } }
另外再提一句原代码的小问题:第一次malloc的2*sizeof(char)是错误的,应该改成2*sizeof(char*),否则在64位系统上,指针大小是8字节,2个char只有2字节,根本存不下两个指针,必然会触发内存越界问题。
内容的提问来源于stack exchange,提问作者Karna
相关产品推荐
相关产品推荐

