You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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]);
}
问题定位与修复方案

核心问题

  1. 每行字符串缺少终止符:拆分每行时仅复制了换行符前的字符,未给lineArray[i]添加'\0'字符串终止符。sprintf()处理%s格式符时依赖终止符判断字符串结束位置,没有终止符会导致越界读取内存,引发输出错乱。
  2. write()写入长度错误:每次调用write都写入了整个1000字节的缓冲区,而sprintf()生成的实际字符串长度远小于缓冲区大小,缓冲区中残留的旧内容会被一并输出,导致错乱。
  3. mmap映射类型冗余:oof作为临时输出缓冲区,使用MAP_SHARED没有必要,换成MAP_PRIVATE即可,但这不是引发错乱的核心原因。

修复步骤

  1. 给每行添加字符串终止符:
    分配内存时多留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++;
    
  2. 精准控制write()写入长度:
    利用sprintf()的返回值(生成的字符串总长度)作为write()的第三个参数,只写入有效内容:
    int output_len = sprintf(oof,"\nlineArray[%d] = %s\n",i,lineArray[i]);
    write(1, oof, output_len);
    
  3. 优化mmap映射类型(可选):
    将oof的映射类型从MAP_SHARED改为MAP_PRIVATE,减少不必要的内存共享开销:
    char *oof = mmap (NULL,buff, PROT_WRITE | PROT_READ ,MAP_PRIVATE| MAP_ANONYMOUS,0,0);
    
  4. 修复内存泄漏:
    程序结束前释放动态分配的内存,解除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:10:13