CentOS7下LRC解析程序内存异常:动态内存申请致数据损坏
问题本质
核心原因是内存越界访问导致堆数据被非法篡改:原结构体中lrc_buf[200]的容量不足以容纳实际写入的内容,溢出的字节覆盖了相邻的lyric_row内存区域,导致链表节点的歌词内容被破坏,遍历出现乱码;扩大lrc_buf到2000后,溢出范围未触及lyric_row,问题暂时隐藏,但内存越界的隐患并未解决。
具体排查方向
字符串溢出验证
检查写入lrc_buf的逻辑:CentOS7默认UTF-8编码,中文占3字节,若某行歌词包含大量中文,实际字节数可能超过200。用strlen()统计写入lrc_buf的内容字节数,确认是否存在超过数组容量的情况。建议替换不安全的strcpy()为snprintf(dest, sizeof(dest), "%s", src),强制限制写入字节数为数组容量减1(留空终止符位置)。结构体内存布局检查
通过GDB查看结构体成员的内存偏移:执行p &struct_instance.lrc_buf和p &struct_instance.lyric_row,确认两者是否相邻。若lrc_buf溢出时的字节数刚好覆盖lyric_row的起始地址,就能直接验证越界覆盖的问题。行分割逻辑边界校验
检查LRC文件按行分割的代码:如果使用fgets()读取行内容,需确认传入的最大读取字节数是否包含换行符和空终止符。若设置为200,当行内容字节数接近200时,fgets()会截断内容,剩余部分会被下一次读取拼接,导致最终写入lrc_buf的内容超长溢出。节点内存分配与初始化检查
确认链表节点的内存分配是否完整:检查malloc()的参数是否为sizeof(你的结构体类型),避免出现分配内存不足的情况。同时验证lyric_row的数组大小是否足够容纳最长的单句歌词,防止自身写入时出现溢出。
内容的提问来源于stack exchange,提问作者programape

