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

C语言中char*返回异常字符串输出问题排查

C语言棋盘打印输出异常:缺失字符串终止符与内存泄漏问题

我有5年Python开发经验,C语言学习不足1年,最近实现棋盘位置打印功能时,代码总是返回奇怪的输出,怀疑是指针相关问题。

相关代码

main函数

int main(int argc, char const *argv[])
{
 POSITION a = STARTPOS;
 printPos(a);
 return 0;
}

POSITION是自定义的typedef struct类型。

printPos函数

void printPos(POSITION pos)
{
    printf("%s\n", getBoardStr(pos));
    printf("%s\n", getBoardStr(pos));
    char * a = getBoardStr(pos);
    printf("%s\n", a);
}

getBoardStr函数

char * getBoardStr(POSITION pos)
{
    BITBOARD i = SIZE_uINT64xCHAR_BIT_1;
    uint8_t iter = 0;
    char * out = malloc(65);
    
    while(i > 0)
    {
         if(pos.WPs & i)      out[iter] = 'P';
         else if(pos.BPs & i) out[iter] = 'p';       
         else if(pos.WNs & i) out[iter] = 'N';
         else if(pos.BNs & i) out[iter] = 'n';         
         else if(pos.WBs & i) out[iter] = 'B';
         else if(pos.BBs & i) out[iter] = 'b';         
         else if(pos.WRs & i) out[iter] = 'R';
         else if(pos.BRs & i) out[iter] = 'r';         
         else if(pos.WQs & i) out[iter] = 'Q';
         else if(pos.BQs & i) out[iter] = 'q';
         else if(pos.WKs & i) out[iter] = 'K';
         else if(pos.BKs & i) out[iter] = 'k';
         
         else
            out[iter] = '.'; 

         i >>= 1;
         ++iter;
    }

    return out;
}

注:BITBOARD是uint64_t的别名,SIZE_uINT64xCHAR_BIT_1代表sizeof(uint64_t)*(CHAR_BIT - 1)。

问题分析

输出异常的核心原因有两个:

  1. 缺失字符串终止符:C语言中printf("%s")要求字符串必须以'\0'(空字符)结尾。getBoardStr分配了65字节内存(刚好存64个棋盘字符+1个终止符),但循环结束后没有添加'\0',导致printf会读取内存中后续的随机垃圾数据,出现乱码。
  2. 内存泄漏:每次调用getBoardStr都会通过malloc分配堆内存,但原代码中没有调用free释放这些内存,长期运行会耗尽系统可用内存。

修复方案

1. 给字符串添加终止符

修改getBoardStr函数,在循环结束后添加'\0',同时增加内存分配失败的判断:

char * getBoardStr(POSITION pos)
{
    BITBOARD i = SIZE_uINT64xCHAR_BIT_1;
    uint8_t iter = 0;
    char * out = malloc(65);
    if (out == NULL) { // 检查内存分配是否成功
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    
    while(i > 0)
    {
         if(pos.WPs & i)      out[iter] = 'P';
         else if(pos.BPs & i) out[iter] = 'p';       
         else if(pos.WNs & i) out[iter] = 'N';
         else if(pos.BNs & i) out[iter] = 'n';         
         else if(pos.WBs & i) out[iter] = 'B';
         else if(pos.BBs & i) out[iter] = 'b';         
         else if(pos.WRs & i) out[iter] = 'R';
         else if(pos.BRs & i) out[iter] = 'r';         
         else if(pos.WQs & i) out[iter] = 'Q';
         else if(pos.BQs & i) out[iter] = 'q';
         else if(pos.WKs & i) out[iter] = 'K';
         else if(pos.BKs & i) out[iter] = 'k';
         
         else
            out[iter] = '.'; 

         i >>= 1;
         ++iter;
    }
    out[iter] = '\0'; // 添加字符串终止符
    return out;
}

2. 释放堆内存

修改printPos函数,每次获取getBoardStr返回的指针后,使用free释放内存:

void printPos(POSITION pos)
{
    char *board1 = getBoardStr(pos);
    printf("%s\n", board1);
    free(board1);
    
    char *board2 = getBoardStr(pos);
    printf("%s\n", board2);
    free(board2);
    
    char *a = getBoardStr(pos);
    printf("%s\n", a);
    free(a);
}

修复效果

添加终止符后,printf能正确识别字符串的结束位置,输出正常的棋盘内容;释放内存则解决了堆内存泄漏问题,避免资源浪费。

内容的提问来源于stack exchange,提问作者leftclick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:50:54