使用sprintf()输出文本行异常问题求助
问题描述
作业要求使用sprintf()及新缓冲区打印文本文件的每行内容,直接用printf()可正常输出,但使用sprintf()后出现输出错乱。推测问题与mmap缓冲区有关,但无法定位修复方案。
相关代码
int buff = 1000; char *ptr = mmap (NULL,buff, PROT_WRITE | PROT_READ ,MAP_PRIVATE| MAP_ANONYMOUS,0,0); if(ptr == MAP_FAILED){ printf("Mapping Failed\n"); return 1; } char *oof = mmap (NULL,buff, PROT_WRITE | PROT_READ ,MAP_SHARED| MAP_ANONYMOUS,0,0); if(oof == MAP_FAILED){ printf("Mapping Failed\n"); return 1; } int f1 = open("file2.txt", O_RDWR); int fd = open("file.txt", O_RDONLY); if(fd < 0){ printf("Uh oh u made an oopsie\n"); }else{ printf("Hey look at that it opened\n\n"); } int length = read(fd,ptr,sizeof(char)*buff); int count = 1; for(int i = 0; i<length;i++){ if(ptr[i] == '\n'){ count++; } } int lengths[count]; for(int i = 0;i<count;i++){ lengths[i] = 0; } int m = 0; for(int i = 0;i<length;i++){ lengths[m]++; if(ptr[i] == '\n'){ m++; } } int j = 0; int k = 0; char **lineArray = (char **) malloc(sizeof(char *) *count); for(int i = 0; i<count; i++){ lineArray[i] = (char *) malloc(sizeof(char)* lengths[i]); k = 0; while(ptr[j] != '\n') { lineArray[i][k] = ptr[j]; j++; k++; } j++; sprintf(oof,"\nlineArray[%d] = %s\n",i,lineArray[i]); write(1,oof,sizeof(char)*buff); //printf("\nlineArray[%d] = %s\n",i ,lineArray[i]); }
问题定位与修复方案
核心问题
- 每行字符串缺少终止符:拆分每行时仅复制了换行符前的字符,未给
lineArray[i]添加'\0'字符串终止符。sprintf()处理%s格式符时依赖终止符判断字符串结束位置,没有终止符会导致越界读取内存,引发输出错乱。 write()写入长度错误:每次调用write都写入了整个1000字节的缓冲区,而sprintf()生成的实际字符串长度远小于缓冲区大小,缓冲区中残留的旧内容会被一并输出,导致错乱。- mmap映射类型冗余:
oof作为临时输出缓冲区,使用MAP_SHARED没有必要,换成MAP_PRIVATE即可,但这不是引发错乱的核心原因。
修复步骤
- 给每行添加字符串终止符:
分配内存时多留1字节用于存储'\0',复制完每行字符后手动添加终止符:lineArray[i] = (char *) malloc(sizeof(char)* (lengths[i] + 1)); // 多分配1字节存终止符 k = 0; while(ptr[j] != '\n') { lineArray[i][k] = ptr[j]; j++; k++; } lineArray[i][k] = '\0'; // 添加字符串终止符 j++; - 精准控制
write()写入长度:
利用sprintf()的返回值(生成的字符串总长度)作为write()的第三个参数,只写入有效内容:int output_len = sprintf(oof,"\nlineArray[%d] = %s\n",i,lineArray[i]); write(1, oof, output_len); - 优化mmap映射类型(可选):
将oof的映射类型从MAP_SHARED改为MAP_PRIVATE,减少不必要的内存共享开销:char *oof = mmap (NULL,buff, PROT_WRITE | PROT_READ ,MAP_PRIVATE| MAP_ANONYMOUS,0,0); - 修复内存泄漏:
程序结束前释放动态分配的内存,解除mmap映射并关闭文件描述符:// 释放lineArray内存 for(int i = 0; i < count; i++){ free(lineArray[i]); } free(lineArray); // 解除mmap映射 munmap(ptr, buff); munmap(oof, buff); // 关闭文件 close(fd); close(f1);
内容的提问来源于stack exchange,提问作者Goodoboi69
相关产品推荐
相关产品推荐

