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

Realloc报错_CrtIsValidHeapPointer(block):动态字符串截断问题求助

动态字符串截断函数的内存错误排查与修复

问题概述

实现动态分配字符串的截断功能时,dstring_truncate函数操作*destination出现异常,运行时realloc触发_CrtIsValidHeapPointer(block)报错,temp变量可正常工作,怀疑指针理解有误,附带dstring_initialize代码请求排查。调用方式为dstring_truncate(&str1, 10),其中DString是char*的别名。

原代码片段

dstring_truncate 函数

void dstring_truncate(DString* destination, unsigned int truncatedLength)
{

    assert(destination != NULL);
    assert(*destination != NULL);
    assert(truncatedLength > 0);

    DString temp = (DString)malloc(strlen(*destination) * sizeof(char));
    strcpy(temp, *destination);
    printf("\n%s test dstring truncate\n", temp);
    temp[truncatedLength] = '\0';
    temp = (DString)realloc(temp, truncatedLength + 1);

    *destination[truncatedLength] = '\0';
    *destination = (DString)realloc(*destination, truncatedLength + 1);
    printf("%s test dstring truncate after realloc\n", *destination);
    
}

dstring_initialize 函数

DString dstring_initialize(const char* str)
{
    assert(str != NULL);
    DString arr = (DString)malloc((strlen(str) + 1) * sizeof(char));
    if (arr == NULL) {
        printf("Memory allocation Failed");
        return NULL;
    }
    strcpy(arr, str);
    if (strcmp(str, arr) == 0) 
    {
        return arr; // Ersatt denna rad. Den ar just nu med for att programmet ska kompilera
    }
}

问题根源与修复方案

1. 指针优先级错误(核心问题)

*destination[truncatedLength]的写法违反运算符优先级规则:数组下标[]的优先级高于解引用*,实际执行的是*(destination[truncatedLength]),这会访问非法内存,直接触发堆指针有效性检查报错。

修正写法:要修改*destination指向的字符串的第truncatedLength位,必须加括号明确优先级:(*destination)[truncatedLength]

2. realloc 操作顺序错误

原代码先给原字符串加\0再调用realloc,看似可行,但如果realloc失败返回NULL,会导致原指针被覆盖,内存泄漏。正确逻辑是先申请新内存,确认成功后再替换原指针并修改字符串。

3. 冗余的 temp 变量

temp变量的存在完全多余,直接操作*destination即可,无需额外分配内存浪费资源。

4. dstring_initialize 的逻辑缺陷

函数中的if (strcmp(str, arr) == 0)判断毫无意义——strcpy成功后两个字符串必然相等,且如果该条件不满足(理论上不可能),函数无返回值,会触发未定义行为。


修复后的完整代码

修复后的 dstring_truncate

void dstring_truncate(DString* destination, unsigned int truncatedLength)
{
    assert(destination != NULL);
    assert(*destination != NULL);

    size_t original_len = strlen(*destination);
    // 新长度大于等于原长度时,无需截断
    if (truncatedLength >= original_len) {
        return;
    }

    // 先执行realloc,失败则保留原指针避免内存泄漏
    DString new_str = (DString)realloc(*destination, truncatedLength + 1);
    if (new_str == NULL) {
        fprintf(stderr, "Realloc failed in dstring_truncate\n");
        return;
    }

    *destination = new_str;
    (*destination)[truncatedLength] = '\0';
    printf("%s test dstring truncate after realloc\n", *destination);
}

修复后的 dstring_initialize

DString dstring_initialize(const char* str)
{
    assert(str != NULL);
    size_t len = strlen(str);
    DString arr = (DString)malloc(len + 1);
    if (arr == NULL) {
        fprintf(stderr, "Memory allocation Failed\n");
        return NULL;
    }
    strcpy(arr, str);
    return arr;
}

额外优化说明

  • 去掉了truncatedLength > 0的断言,允许截断到空字符串,逻辑更灵活。
  • 使用fprintf(stderr)输出错误信息,符合标准错误输出规范。
  • 增加原长度判断,避免不必要的内存操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:54:50