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

使用Valgrind排查程序错误遇阻,寻求代码修改方案

Fixing Valgrind's Invalid Read Error in Your C String Reverse Function

Let's break down exactly what's going on here and fix the issue step by step. First, let's parse Valgrind's key error message:

14892 Invalid read of size 1
14892 at 0x4C32D44: __strlen_sse2 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
14892 Address 0x522d04c is 0 bytes after a block of size 12 alloc'd

This means your code is reading memory right after the end of a block you allocated with malloc. The problem boils down to how you're handling C string termination—something that's easy to overlook but critical for proper string behavior.

The Root Problems in Your Code

C strings depend on a null terminator ('\0') to tell functions like printf or strlen where the string ends. Here's where you went wrong:

  1. Insufficient memory allocation: You used malloc(strlen(text)), but strlen() returns the length of the string excluding the null terminator. Your reversed string needs an extra byte to store this '\0'.
  2. Missing null terminator: After copying and reversing characters, you never added the '\0' to the end of your new string. This makes functions like printf keep reading past your allocated memory until they hit a random null byte, triggering Valgrind's error.

Corrected Code with Explanations

Here's the fixed version of your code, with notes on each change:

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

char* reverse(const char* text){
    if(text == NULL){
        return NULL;
    }
    size_t len = strlen(text); // Store the string length once (avoids repeated slow strlen calls)
    // Allocate len + 1 bytes to make space for the null terminator
    char *novy = malloc(len + 1);
    if (novy == NULL) { // Always check if malloc succeeded (prevents crashes from out-of-memory)
        return NULL;
    }
    
    // Copy and uppercase the original string's characters
    for(size_t j = 0; j < len; j++){
        novy[j] = toupper(text[j]);
    }
    // Add the null terminator to mark the end of our new string
    novy[len] = '\0';
    
    size_t p = len - 1;
    for(size_t i = 0; i < (len / 2); i++){
        char tmp = novy[i];
        novy[i] = novy[p];
        novy[p] = tmp;
        p--;
    }
    return novy;
}

int main(){
    char* reversed = reverse("Hello world!");
    if (reversed != NULL) { // Check for NULL to avoid printing a invalid pointer
        printf("%s\n", reversed);
        free(reversed);
    }
    return 0;
}

Key Fixes Explained

  • Extra byte for null terminator: malloc(len + 1) ensures we have space for both the string characters and the '\0'.
  • Explicit null terminator: novy[len] = '\0' tells string-handling functions exactly where our string ends.
  • Cached string length: Storing strlen(text) in len once improves efficiency (since strlen scans the entire string each time it's called) and keeps our code consistent.
  • Null safety checks: Adding checks for malloc failure and reverse returning NULL prevents potential crashes from edge cases.

Why This Fixes Valgrind's Error

With the null terminator in place and enough memory allocated, functions like printf will stop reading exactly at the end of your allocated block. Valgrind will no longer detect an "invalid read," and your string will behave as expected. The heap summary already showed no memory leaks, so this resolves the only error in your code.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 19:27:26