动态数组分配问题:valgrind报条件跳转依赖未初始化值
问题分析与修复
你的问题核心是动态分配的字符串没有添加字符串终止符'\0',同时初始分配的内存未初始化,导致strlen读取到未定义的内存区域,触发valgrind的警告。
具体问题点
strlen的工作逻辑是从起始地址开始遍历,直到遇到'\0'才停止计数。你的代码仅将输入字符存入数组,但未在末尾添加这个终止符。malloc分配的内存是未初始化的(内存中是随机脏数据),如果输入字符数小于初始分配的10个,msg数组后续的内存是未定义状态,strlen会持续读取这些脏数据,直到碰巧遇到'\0',这直接导致了valgrind的"Conditional jump or move depends on uninitialised value(s)"错误。
修复步骤
- 添加字符串终止符:输入循环结束后,在
msg[idx]位置写入'\0',确保strlen能正确识别字符串边界。 - 调整内存分配空间:初始分配和后续扩容时,多预留1个字节的空间给
'\0',避免数组越界。 - 可选:初始化内存:可以用
calloc替代malloc(自动将内存初始化为0),或用memset手动初始化,即使输入长度不足,后续内存也会是'\0',进一步提升安全性。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main() { char* msg = NULL; int c; // 初始分配10个字符空间 + 1个字节存'\0' size_t size = 10; msg = malloc(sizeof(char) * (size + 1)); if (msg == NULL) { // 必须检查内存分配是否成功 perror("malloc failed"); exit(EXIT_FAILURE); } int idx = 0; char* temp = NULL; while (1) { c = getchar(); if (c == EOF || c == '\n') { break; } else if (!isalpha(c)) { free(msg); exit(100); } // 检查当前索引是否耗尽可用空间(预留1位给'\0') if (size <= idx) { size *= 2; // 扩容为原大小的2倍 temp = realloc(msg, sizeof(char) * (size + 1)); if (temp == NULL) { // 检查扩容是否成功 free(msg); perror("realloc failed"); exit(EXIT_FAILURE); } msg = temp; } msg[idx++] = (char)c; } // 写入字符串终止符,确保strlen正常工作 msg[idx] = '\0'; printf("%ld\n", strlen(msg)); free(msg); // 释放内存,避免泄漏 return 0; }
额外注意事项
- 每次调用
malloc和realloc后,必须检查返回值是否为NULL,防止内存分配失败导致程序崩溃。 - 最后务必调用
free(msg)释放动态分配的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Shaxey
相关产品推荐
相关产品推荐

