malloc分配char*字符串后出现未知字符,求原因及解决办法
malloc分配的字符串开头出现未知字符的原因及解决方法
先看你提供的代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ int temptn; char *ticno, temptn2[10]; ticno = (char*)malloc(100); printf("%s", ticno); for (int i=0; i < 6; i++){ temptn = i; sprintf(temptn2, "%d", temptn); strcat(ticno, temptn2); } printf("\n%s", ticno); // prints &┐012345 }
问题原因
malloc()只会从堆上分配指定大小的内存块,但不会对内存做任何初始化,里面的内容是堆内存中残留的随机垃圾数据。而C语言中字符串的识别完全依赖末尾的'\0'(空字符):
- 第一次调用
printf("%s", ticno)时,因为ticno指向的内存没有'\0',printf会持续读取内存字节,直到遇到某个随机出现的'\0',这段过程中读取到的垃圾字符就会被打印出来。 strcat()的工作逻辑是先在目标字符串中找到'\0'的位置,再把源字符串追加到这里。因为ticno初始没有'\0',strcat会在内存中盲目查找,最终导致追加的内容前面带着未被覆盖的垃圾数据,就出现了你看到的&┐012345这类输出。
解决方法
核心就是让malloc分配的内存一开始就是合法的空字符串(即首字节为'\0'),有三种常用方式:
方式1:手动初始化首字节为'\0'
如果只需要保证字符串合法,不需要清空全部内存,直接设置首字符为空即可:
ticno = (char*)malloc(100); ticno[0] = '\0'; // 关键:初始化空字符串
方式2:用memset清空整个内存块
如果需要把分配的内存全部置为0(避免其他潜在的垃圾数据问题),可以用memset:
#include<string.h> // 需要包含头文件 ticno = (char*)malloc(100); memset(ticno, 0, 100); // 将100字节全部设为0
方式3:用calloc替代malloc
calloc()函数在分配内存的同时,会自动把所有字节初始化为0,一步到位:
ticno = calloc(100, sizeof(char)); // 等价于malloc+memset(0)
优化后的完整代码
#include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ int temptn; char *ticno, temptn2[10]; ticno = (char*)malloc(100); ticno[0] = '\0'; // 初始化空字符串 printf("%s", ticno); // 现在输出空内容 for (int i=0; i < 6; i++){ temptn = i; sprintf(temptn2, "%d", temptn); strcat(ticno, temptn2); } printf("\n%s", ticno); // 输出012345 free(ticno); // 记得释放堆内存,避免泄漏 return 0; }
注意:使用malloc/calloc分配的内存,一定要在使用完后用free()释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Leon Loo
相关产品推荐
相关产品推荐

