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
相关产品推荐
相关产品推荐

