free(): invalid

KMP算法中free错误解析
本文探讨了在实现KMP字符串匹配算法时遇到的内存管理问题,具体为使用malloc分配内存后free时出现的错误,并详细分析了问题原因及解决办法。

写KMP字符串匹配算法的时候,遇到malloc申请内存,free的时候报错:

*** glibc detected *** ./strdel: free(): invalid next size (fast): 0x09868008 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0xcad591]
/lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0xcaede8]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0xcb1ecd]
./strdel[0x8048782]
./strdel[0x80487f5]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xc58bd6]
./strdel[0x8048421]
======= Memory map: ========
005e0000-005e1000 r-xp 00000000 00:00 0          [vdso]
00837000-00852000 r-xp 00000000 08:03 131097     /lib/ld-2.11.1.so
00852000-00853000 r--p 0001a000 08:03 131097     /lib/ld-2.11.1.so
00853000-00854000 rw-p 0001b000 08:03 131097     /lib/ld-2.11.1.so
00bfc000-00c19000 r-xp 00000000 08:03 131075     /lib/libgcc_s.so.1

很明显是free(next)函数引起的。


程序部分原代码如下:

char* delkmpstr(const char *str, const char *ss)
{
    int i, j, k;
    int *next, *delpos;
    char *ret = 0;
    int str_len = strlen(str);
    int ss_len = strlen(ss);
    
    next = (int *)malloc(ss_len*sizeof(int));
    if(!next){
        printf("malloc next error\n");
        return 0;
    }
    
    getnext(ss, next);
................


void getnext(const char *ss, int *next)
{
    int i, j;
    int ss_len = strlen(ss);

    //printf("ss_len: %d\n", ss_len);

    i = 0;
    j = -1;
    next[0] = -1;
    while(i < ss_len){
        if(j == -1 || ss[i] == ss[j]){
            ++i;
            ++j;
            next[i] = j;
        }else{
            j = next[j];
        }
    }
}


这个函数就是获取模式串的next函数值,经过查询引起free错误的原因可能是调用函数过程中next指针改变或者是越界赋值。

用gdb调试后,发现malloc和free时,next指针值相同。

那可能就是越界赋值了。

在getnext中的while(i < ss_len) 这行

当i为ss_len-1时,++i,i变成ss_len,next[i] = j;越界了。。。

改为while(i < ss_len-1)就运行正常了。






<think>我们正在处理一个关于C/C++程序中"free(): invalid pointer"错误的问题。用户希望了解导致此错误的原因以及如何修复它。 根据引用[4],我们知道Memcheck(Valgrind的工具)可以检测内存错误,包括无效指针的释放。此外,引用[3]中提到一个关于空指针访问的bug修复,虽然不直接相关,但说明指针错误是常见的。 错误原因分析: 1. 尝试释放一个未通过malloc/calloc/realloc分配的指针。 2. 尝试释放一个已经释放过的指针(双重释放)。 3. 指针被覆盖(例如,指针被修改指向了非堆内存区域,或者指向了分配内存的中间部分,而不是起始位置)。 4. 指针越界:例如,指针在分配的内存区域之外。 5. 使用已释放的指针(释放后再次使用,或者释放后再次释放)。 解决方法: 1. 使用内存检测工具(如Valgrind)来定位问题。Valgrind可以报告无效的释放操作以及内存泄漏等。 2. 检查代码中分配和释放的匹配性,确保每一个malloc都有对应的free,且只free一次。 3. 确保指针没有被意外修改(例如,指针算术运算错误)。 4. 避免返回指向栈内存的指针(局部变量)给调用者,因为栈内存在函数返回后会被释放。 步骤: 1. 使用Valgrind运行程序:`valgrind --leak-check=full ./your_program` 2. 根据Valgrind的输出,定位到具体的代码行。 3. 检查相关指针的分配和释放情况。 示例代码错误: ```c #include <stdlib.h> int main() { int *p = (int*)malloc(10 * sizeof(int)); p++; // 修改指针,使其不再指向分配内存的起始位置 free(p); // 错误:释放的指针不是malloc返回的指针 return 0; } ``` 运行Valgrind会报告无效释放。 另一个常见错误:释放栈上分配的数组 ```c int main() { int arr[10]; int *p = arr; free(p); // 错误:arr不是堆内存 return 0; } ``` 因此,修复的关键是确保传递给free指针必须是由malloc/calloc/realloc返回的,且未被修改,且未被释放过。 另外,引用[1]中提到了C++中返回方式(值传递和引用传递)的问题,虽然不直接相关,但提醒我们在传递指针时要小心所有权问题,避免多个指针指向同一块内存而导致重复释放。 建议: 1. 在C++中,使用智能指针(如std::unique_ptr, std::shared_ptr)可以避免手动管理内存,减少此类错误。 2. 在C中,确保分配和释放的对称性,并避免指针运算导致指针改变(除非保存原始指针)。 如果用户使用的是C++,推荐使用RAII(资源获取即初始化)技术,例如: ```cpp #include <memory> int main() { auto p = std::make_unique<int[]>(10); // 不需要手动释放,当p离开作用域时会自动释放 return 0; } ``` 总结:解决"free(): invalid pointer"的关键是检查指针的有效性,确保它指向堆内存的起始位置,并且未被释放过。使用工具如Valgrind可以帮助定位问题。 生成相关问题: 1. 如何用Valgrind检测内存错误? 2. 在C++中,智能指针如何避免内存错误? 3. 什么是双重释放?如何避免? 4. 指针运算错误如何导致无效指针? 5. 如何调试C/C++程序的内存错误?</think>### C/C++ "free(): invalid pointer" 错误分析与解决 `free(): invalid pointer` 错误发生在尝试释放无效内存指针时,通常由以下原因引起: #### 🔍 常见原因 1. **释放非堆内存** 尝试释放栈内存或全局变量: ```c int stackVar; free(&stackVar); // 错误:栈内存 static int globalVar; free(&globalVar); // 错误:全局变量 ``` 2. **指针被覆盖** 指针被修改后不再指向分配内存的起始地址: ```c int* ptr = malloc(10 * sizeof(int)); ptr += 5; // 指针偏移 free(ptr); // 错误:非原始地址 ``` 3. **双重释放** 重复释放同一指针: ```c int* ptr = malloc(sizeof(int)); free(ptr); free(ptr); // 错误:ptr已失效 ``` 4. **越界写入** 缓冲区溢出导致内存控制结构损坏: ```c int* arr = malloc(5 * sizeof(int)); arr[5] = 42; // 越界写入 free(arr); // 可能触发错误 ``` 5. **使用已释放内存** 释放后继续使用指针: ```c free(ptr); ptr->data = 10; // 非法访问 ``` #### 🛠️ 解决方法 1. **使用内存检测工具** 通过 Valgrind 定位问题: ```bash valgrind --leak-check=full --show-leak-kinds=all ./your_program ``` 输出示例: ``` Invalid free() / delete / delete[] / realloc() at 0x483CA3F: free (vg_replace_malloc.c:530) by 0x1091FE: main (example.c:15) Address 0x1fff000000 is on thread 1's stack ``` 2. **代码审查要点** - 确保每个 `malloc` 对应唯一 `free` - 释放后立即置空指针:`free(ptr); ptr = NULL;` - 避免指针算术运算后直接释放 - 检查数组边界访问 3. **防御性编程技巧** ```c #ifdef DEBUG #define SAFE_FREE(p) do { \ if ((p) != NULL) { \ free(p); \ (p) = NULL; \ } \ } while(0) #else #define SAFE_FREE(p) free(p) #endif ``` 4. **C++替代方案** 使用智能指针避免手动管理: ```cpp #include <memory> std::unique_ptr<int[]> arr(new int[10]); // 自动释放 ``` #### 📌 关键预防措施 1. 始终初始化指针:`int* ptr = NULL;` 2. 避免返回局部变量指针 3. 复杂项目使用自定义内存分配器 4. 开启编译器警告:`gcc -Wall -Wextra -g` > 引用[4]指出:Valgrind 的 Memcheck 工具可检测 "definitely lost"(绝对泄漏)、"indirectly lost"(间接泄漏)等内存问题,通过 `--leak-check=full` 可精确定位无效指针错误[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值