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

解析Valgrind输出中的"Invalid read of size"错误

Valgrind无效读取问题分析

我在测试动态存储字符串的代码时,Valgrind提示存在无效读取操作,但我认为内存分配逻辑正确,想找出被忽略的问题。

测试代码

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

char *array[4]={"str1", "str4", "str0", "str2"};
int arr_index = 0;

char* get_array(void)
{

    if (arr_index >= (sizeof(array)/sizeof(array[0])))
    {
        return NULL;
    }
    else
    {
        return array[arr_index];
    }
}

int main(void)
{
    char **orderIds = malloc(0);
    char *tmp=NULL;
    int variableNumberOfElements=0;

    for(int i = 0; i < 10; i++) {
        tmp = get_array();
        if(tmp == NULL)
        {
            break;
        }
        arr_index++;
        variableNumberOfElements++;
        orderIds = realloc(orderIds, variableNumberOfElements * sizeof(char*));
        orderIds[i] = malloc(strlen(tmp) * sizeof(char));
        strncpy(orderIds[i], tmp, strlen(tmp));
    }

    for(int j=0; j<variableNumberOfElements; j++)
    {
        printf("%s\n", orderIds[j]);
    }
    for(int x=0; x<=variableNumberOfElements; x++)
    {
        free(orderIds[x]);
    }

    free(orderIds);
    exit(0);
}

Valgrind输出

==27260== Memcheck, a memory error detector
==27260== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27260== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==27260== Command: ./a.out
==27260== 
==27260== Invalid read of size 1
==27260==    at 0x484ED24: strlen (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==27260==    by 0x48F1EE7: puts (ioputs.c:35)
==27260==    by 0x109357: main (test.c:42)
==27260==  Address 0x4a9c0d4 is 0 bytes after a block of size 4 alloc'd
==27260==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==27260==    by 0x1092E6: main (test.c:36)
==27260== 
str1
str4
str0
str2
==27260== Invalid read of size 8
==27260==    at 0x109381: main (test.c:46)
==27260==  Address 0x4a9c290 is 0 bytes after a block of size 32 alloc'd
==27260==    at 0x484DCD3: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==27260==    by 0x1092B8: main (test.c:35)
==27260== 
==27260== 
==27260== HEAP SUMMARY:
==27260==     in use at exit: 0 bytes in 0 blocks
==27260==   total heap usage: 10 allocs, 10 frees, 1,120 bytes allocated
==27260== 
==27260== All heap blocks were freed -- no leaks are possible
==27260== 
==27260== For lists of detected and suppressed errors, rerun with: -s
==27260== ERROR SUMMARY: 5 errors from 2 contexts (suppressed: 0 from 0)

问题分析与修复

Valgrind的两个无效读取错误对应代码里的两个问题:

  1. 字符串未分配终止符空间

    • 代码中malloc(strlen(tmp) * sizeof(char))只分配了字符串内容的字节数,但C字符串需要末尾的'\0'标记结束。比如"str1"的长度是4,实际需要5字节存储(4个字符+1个终止符)。
    • 当printf调用strlen读取字符串时,会越过分配的内存边界寻找'\0',触发Invalid read of size 1。
    • 修复:分配内存时额外预留1字节,并手动添加终止符,或者用strdup简化操作:
      // 方案1:手动处理
      orderIds[i] = malloc(strlen(tmp) + 1);
      strncpy(orderIds[i], tmp, strlen(tmp));
      orderIds[i][strlen(tmp)] = '\0';
      // 方案2:用strdup自动处理
      orderIds[i] = strdup(tmp);
      
  2. free循环越界访问

    • 代码中for(int x=0; x<=variableNumberOfElements; x++)的条件错误,variableNumberOfElements是数组元素个数,下标范围是0到variableNumberOfElements-1,x<=会访问orderIds[variableNumberOfElements],超出realloc分配的内存范围,触发Invalid read of size 8(64位系统指针占8字节)。
    • 修复:将循环条件改为x < variableNumberOfElements。

修正后的核心代码片段

// 循环内字符串分配部分
orderIds[i] = strdup(tmp);

// free循环部分
for(int x=0; x < variableNumberOfElements; x++)
{
    free(orderIds[x]);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:20:30