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

Valgrind报Conditional jump错误排查:已初始化变量仍触发问题

解决Valgrind提示的“Conditional jump or move depends on uninitialised value(s)”问题

你的代码功能正常,但触发Valgrind未初始化内存错误的核心原因是:normalize_wspace2的for循环处理末尾空白时,i会被递增到字符串终止符'\0'的下一个位置,此时循环条件检查_str[i] != '\0'会访问栈上未初始化的内存。

错误触发流程

  1. 原字符串末尾是连续空白时,进入空白判断分支,执行while循环跳过所有空白,最终i指向'\0'。
  2. 执行_str[j] = _str[i],把'\0'写入目标位置。
  3. 执行for循环的j++, i++,此时i指向'\0'的下一个字节——这部分属于栈上未初始化的内存。
  4. 循环条件检查_str[i] != '\0',访问了未初始化的值,触发Valgrind报错。

另外del_twspace函数存在隐患:如果输入字符串全是空白字符,last_char会保持初始值-1,执行s[last_char + 1] = '\0'虽然不会崩溃,但逻辑不严谨。

修复后的代码

#include "main.h"
#include <stdio.h>
#include <ctype.h>

void normalize_wspace2(char *_str);
void del_twspace(char *s);

int main(void)
{
    char s[] = " ls       -la f1\t folder2 this one\t\t    ";

    printf("s initial = %s,\n", s);
    normalize_wspace2(s);
    printf("s normalized = %s,\n", s);
}

void normalize_wspace2(char *_str)
{
    size_t i = 0, j = 0;
    // 跳过开头所有空白
    while (isspace((unsigned char)_str[i])) {
        i++;
    }

    for (; _str[i] != '\0'; i++) {
        if (isspace((unsigned char)_str[i])) {
            // 写入单个空格
            _str[j++] = ' ';
            // 跳过后续所有空白
            while (isspace((unsigned char)_str[++i])) {
                if (_str[i] == '\0') break;
            }
            // 提前遇到终止符就退出循环
            if (_str[i] == '\0') break;
        }
        // 复制非空白字符
        _str[j++] = _str[i];
    }
    _str[j] = '\0';
    del_twspace(_str);
}

void del_twspace(char *s)
{
    if (s == NULL) {
        fprintf(stderr, "error: del_twspace passed null\n");
        return;
    }

    size_t last_non_ws = 0;
    int has_non_ws = 0;
    size_t i = 0;

    while (s[i] != '\0') {
        if (!isspace((unsigned char)s[i])) {
            last_non_ws = i;
            has_non_ws = 1;
        }
        i++;
    }

    // 处理全空白字符串的情况
    if (has_non_ws) {
        s[last_non_ws + 1] = '\0';
    } else {
        s[0] = '\0';
    }
}

关键修复说明

  • normalize_wspace2:
    • 先跳过开头空白,避免生成以空格开头的字符串。
    • 重构循环逻辑,确保i不会越过'\0',彻底避免访问未初始化内存。
    • 用isspace简化空白判断,覆盖所有标准空白字符(空格、制表符、垂直制表符等),代码更简洁。
  • del_twspace:
    • 新增has_non_ws标记,处理全空白字符串的边界情况,避免last_char为-1的问题。
    • 把perror换成fprintf,因为perror用于系统调用错误,这里是参数错误,更合适。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:47:42