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

char[]截断后出现多余字符的问题排查与修复咨询

问题修复:char[]截断后出现多余字符

问题现象

按指定长度截断char[]时,新数组频繁出现乱码,不同截断长度表现如下:

  • 截取1/2个字符时,结果带冗余乱码:
    @▬w @▬n @▬k @▬a  // 预期为d、n、k、a的反转结果
    @id @an @ok @la   // 预期为di、an、ok、la的反转结果
    
  • 截取3个字符时结果正常:
    nid ran rok mla
    
  • 截取超过3个字符时再次出现乱码:
    qp░nnid qp░aran qp░trok qp░amla 
    
  • 截取长度超过最长行时结果正常:
    eynnid scnaran etrok amla  
    

问题代码

char **read(FILE *file, int lineLength, int *pLines)
{
    size_t total = 0;
    size_t allocated = START;

    int sor = 0;

    char buffer[MAX_LENGTH];
    char shortened[lineLength];
/////////
    //printf("%d", sizeof(shortened));
    char **lines= (char **)malloc(allocated* sizeof(char *));

    while (fgets(buffer, MAX_LENGTH, file) != NULL)
    {
        for (int i = 0; i < lineLength; i++)
        {
            shortened[i] = buffer[i];
        }

        int length = strlen(shortened);
        if (shortened[length - 1] == '\n')
        {
            shortened[length - 1] = '\0';
        }
        if (line == allocated)
        {
            allocated*= 2;
            lines= realloc(sorok, allocated* sizeof(char *));
        }
        lines[line] = (char *)malloc(lineLength);

        strcpy(lines[line], shortened);
        line++;
    }
    *pLines = line;
    return lines;
}

修复要点及修正代码

核心问题分析

  1. 字符串无终止符:C语言字符串必须以'\0'结尾,strlen、strcpy等函数依赖它识别边界。直接复制lineLength个字符后,shortened未添加终止符,导致函数越界读取内存产生乱码。
  2. 内存分配不足:malloc(lineLength)仅分配lineLength字节,但存储截断后的字符串需要额外1字节存'\0',否则strcpy会越界写入。
  3. 变量名错误:代码中出现未定义的line、sorok变量,属于笔误(sor应为line,sorok应为lines)。
  4. 换行符处理越界:若截断长度小于原行长度,换行符不在shortened内,此时访问shortened[length-1]会越界。

修复后的代码

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define START 4
#define MAX_LENGTH 1024

char **read(FILE *file, int lineLength, int *pLines)
{
    size_t allocated = START;
    int line = 0;  // 修正变量名,替换原未使用的sor

    char buffer[MAX_LENGTH];
    // 给shortened多留1字节存终止符
    char shortened[lineLength + 1];

    char **lines = (char **)malloc(allocated * sizeof(char *));
    if (!lines) return NULL;  // 新增内存分配失败判断

    while (fgets(buffer, MAX_LENGTH, file) != NULL)
    {
        // 复制指定长度字符
        memcpy(shortened, buffer, lineLength);
        // 强制添加字符串终止符,确保strlen等函数正常工作
        shortened[lineLength] = '\0';

        // 处理换行符:仅当截断后的字符串末尾是换行符时替换
        size_t len = strlen(shortened);
        if (len > 0 && shortened[len - 1] == '\n')
        {
            shortened[len - 1] = '\0';
        }

        // 扩容逻辑修正:使用正确的变量名lines
        if (line == allocated)
        {
            allocated *= 2;
            char **temp = realloc(lines, allocated * sizeof(char *));
            if (!temp) {
                // 内存分配失败时,先释放已分配的内存避免泄漏
                for (int i = 0; i < line; i++) free(lines[i]);
                free(lines);
                *pLines = 0;
                return NULL;
            }
            lines = temp;
        }

        // 分配内存时+1,预留终止符位置
        lines[line] = (char *)malloc(strlen(shortened) + 1);
        if (!lines[line]) {
            // 内存分配失败时清理资源
            for (int i = 0; i < line; i++) free(lines[i]);
            free(lines);
            *pLines = 0;
            return NULL;
        }
        strcpy(lines[line], shortened);
        line++;
    }

    *pLines = line;
    return lines;
}

关键修复说明

  • 强制添加终止符:复制lineLength个字符后,直接设置shortened[lineLength] = '\0',确保字符串边界正确。
  • 内存分配修正:malloc(strlen(shortened)+1)仅分配实际需要的内存(也可使用lineLength+1,前者更节省空间)。
  • 变量名修正:替换未定义变量,避免编译错误。
  • 内存安全优化:添加内存分配失败的判断与资源清理,避免内存泄漏。
  • 换行符处理优化:先判断字符串长度大于0,再访问末尾字符,避免越界。

内容的提问来源于stack exchange,提问作者Đániel Labanc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:16:14