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

排查两数之和(非唯一配对)代码的段错误问题

排查两数之和代码的段错误问题

我帮你仔细看了这段找数组中和为指定值的数对的代码,段错误的根源有好几个关键问题,咱们一个个拆解:

1. 返回指针ret未初始化且内存分配错误

你声明了int **ret;但完全没给它分配内存,直接就用ret[i] = a;往里面存数据,这相当于直接访问非法内存,必然会触发段错误。而且数对的数量不一定等于数组的长度size,不能直接按size来分配内存,得先统计符合条件的数对数量,再按需分配。

2. bsearch的参数错误且数组未排序

bsearch要求数组必须是已排序的,但你的代码里不管是调用twoSum前还是函数内部,都没有对数组进行排序,这会导致查找结果完全不可靠,甚至触发未定义行为。另外,bsearch的第四个参数是单个元素的大小,你写的sizeof(arr)/sizeof(arr[0])是错误的——因为函数参数里的arr是指针,不是数组,sizeof(arr)得到的是指针的字节数(比如64位系统是8),除以sizeof(arr[0])(4)会得到2,这和实际元素大小sizeof(int)不符,会让bsearch的内存访问逻辑混乱。

3. 局部数组a的内存会被释放

你在循环里创建的int a[2]是栈上的局部变量,当循环迭代或者函数结束后,这块内存会被系统回收,ret[i]指向的就是无效内存,后续在main里访问res[i][0]时就会触发段错误或者读取到乱码。应该用malloc动态分配每个数对的内存,这样内存会一直保留到你手动释放。

4. else分支非法访问空指针

在else里你写了printf("could not find item = %d\n", *result);,但此时result是NULL,直接解引用空指针会立刻触发段错误,这部分必须删掉。

5. 重复数对与自配对问题

原代码会把同一个数对反过来存两次(比如找到1和8后,遍历到8时又会找1),如果数组里有重复元素,还会出现自己和自己配对的情况(比如sum=4时,数组里的2会和自己配对),需要限制查找范围在当前元素的后面,避免重复。


修正后的完整代码

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

int compare(const void *l, const void *r) {
    return *(int *)l - *(int *)r;
}

int **twoSum(int *arr, int sum, int size, int *returnSize) {
    // 先对数组排序,满足bsearch的要求
    qsort(arr, size, sizeof(int), compare);
    
    // 先统计符合条件的数对数量
    int count = 0;
    for (int i = 0; i < size; i++) {
        // 跳过重复元素,避免生成重复数对
        if (i > 0 && arr[i] == arr[i-1]) {
            continue;
        }
        int diff = sum - arr[i];
        // 在i+1到末尾的范围内查找diff,避免自配对和重复
        int *result = (int*)bsearch(&diff, arr + i + 1, size - i - 1, sizeof(int), compare);
        if (result != NULL) {
            count++;
        }
    }
    
    // 分配结果数组的内存
    int **ret = (int**)malloc(count * sizeof(int*));
    if (ret == NULL) {
        *returnSize = 0;
        return NULL;
    }
    
    // 再次遍历,填充结果
    int idx = 0;
    for (int i = 0; i < size; i++) {
        if (i > 0 && arr[i] == arr[i-1]) {
            continue;
        }
        int diff = sum - arr[i];
        int *result = (int*)bsearch(&diff, arr + i + 1, size - i - 1, sizeof(int), compare);
        if (result != NULL) {
            // 动态分配每个数对的内存
            int *pair = (int*)malloc(2 * sizeof(int));
            pair[0] = arr[i];
            pair[1] = *result;
            ret[idx++] = pair;
        }
    }
    
    *returnSize = count;
    return ret;
}

int main(int argc, char const *argv[]) {
    int arr[9] = {1,2,4,3,6,2,7,0,10};
    int returnSize = 0;
    int** res = twoSum(arr, 9, 9, &returnSize);
    
    // 只遍历有效数对的数量
    for (int i = 0; i < returnSize; i++) {
        printf("[%d,%d]\n", res[i][0], res[i][1]);
        // 记得释放每个数对的内存
        free(res[i]);
    }
    // 释放结果数组的内存
    free(res);
    
    return 0;
}

主要修改说明:

  • 新增returnSize参数,用来返回有效数对的数量,避免在main里遍历整个数组长度
  • 先对数组排序,满足bsearch的要求
  • 先统计数对数量,再按需分配内存
  • 限制bsearch的查找范围在当前元素之后,避免重复数对和自配对
  • 用malloc动态分配数对内存,避免局部变量内存被回收
  • 在main里添加内存释放逻辑,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:53:10