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

C语言递归过深触发Segmentation fault 如何保障程序持续运行

问题背景

我有一个递归函数,用于校验不同参数组合的有效性,校验通过的组合会被添加到数组中。当组合量较小时程序运行正常,但运行时间较长时就会抛出Segmentation fault错误。我基本可以确定错误是递归深度过高导致的,因为我将第一个参数的逻辑从递归改为for循环后,程序的运行时长明显变长。

原有问题代码

int* add_without_overflow(tp_t* parameters, int arr[10], int position, int num_parameters, int *size, int* ptr) {
  if(arr[position] > parameters[position].max){
        if(position != 0){
            arr[position] = parameters[position].min;
            arr[position-1]++;
            add_without_overflow(parameters, arr, position-1, num_parameters, size, ptr);
        }
        else{
            return ptr;
        }
  }
  else{
        if(position == num_parameters-1){
           if((parameters[position].constraint)(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9])){
              print_configuration(arr, num_parameters);
              ptr = (int*)realloc(ptr, (((*size) +1)*num_parameters) * sizeof(int));
              for(int i = 0; i < num_parameters; i++){
                ptr[((*size)*num_parameters) + i] = arr[i];
              }
              (*size)++;
           }
           arr[position]++;
           add_without_overflow(parameters, arr, position, num_parameters, size, ptr);
        }
        else{
            if(parameters[position].constraint != 0  && !(parameters[position].constraint)(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9])){
               for(int i = position+1; i < num_parameters; i++){
                      arr[i] = parameters[i].min;
               }
               arr[position]++;
               add_without_overflow(parameters, arr, position, num_parameters, size, ptr);
            }
            else{
               add_without_overflow(parameters, arr, position+1, num_parameters, size, ptr);
            }
        }
  }
}


void generate_search_space(tp_t* parameters, int num_parameters,
                           search_space_t* search_space) {
  int arr[10];
  for (int i = 0; i < num_parameters; i++){
        arr[i] = parameters[i].min;   
  }
  int size = 0;
  int *sizepointer = &size;
  int *ptr;
  ptr = (int *)malloc(((0) * num_parameters) * sizeof(int));
  ptr = add_without_overflow(parameters, arr, 0, num_parameters, sizepointer, ptr);
  for(int i = 0; i < num_parameters; i++){
      search_space-> parameters[i] = &parameters[i];
  }
  
  search_space->size = size;
  search_space->num_parameters = num_parameters;
  search_space->values = ptr;
}

测试情况与待解决问题

第一轮测试校验256种可能的组合,编译运行都正常。第二轮测试要校验总计128^6种组合(实际不需要全部校验,初始版本代码遍历所有组合要运行数小时,优化后的版本可以一次性排除多组无效组合)。
需要解决的核心问题:怎么避免递归过多导致的程序崩溃?还是说这个场景不适合用递归函数,需要完全重写代码?


问题解决

根因分析

原有代码的问题并非无法执行到return语句(在特定场景下它是可以到达的),而是它采用单一路径遍历所有配置,所有递归调用都会等待最终函数调用返回结果。小体量测试下该逻辑没有问题,但在大体量测试中会生成数千甚至数百万个等待返回的函数调用,数量过多就会触发Segmentation fault错误。

优化后代码

void add_to_search_space(tp_t* parameters, int arr[10], int position, int num_parameters, int *size, int** pptr){
   if(position == num_parameters-1){
          
          while(arr[position] < parameters[position].max+1){
                if((parameters[position].constraint)(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9])){
                    print_configuration(arr, num_parameters);
                    *pptr = realloc(*pptr, (((*size) +1)*num_parameters)* sizeof(int));
                    
                    for(int j = 0; j < num_parameters; j++){
                         (*pptr)[(*size*num_parameters) + j] = arr[j];
                    }
                    (*size)++;
                }
                arr[position]++;
          }
   }
   else{
          
          while(arr[position] < parameters[position].max+1){
                if(parameters[position].constraint == 0  || (parameters[position].constraint)(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9])){
                    add_to_search_space(parameters, arr, position+1, num_parameters, size, pptr);
                }
                for(int i = position+1; i < num_parameters; i++){
                     arr[i] = parameters[i].min;
                }
                arr[position]++;
          }
   }
}

void generate_search_space(tp_t* parameters, int num_parameters,
                           search_space_t* search_space) {
  int arr[10];
  for (int i = 0; i < num_parameters; i++){
        arr[i] = parameters[i].min;   
  }
  int size = 0;
  int *sizepointer = &size;
  int *ptr;
  ptr = (int *)malloc(((0) * num_parameters) * sizeof(int));
  int **pptr;
  pptr = &ptr;
  add_to_search_space(parameters, arr, 0, num_parameters, sizepointer, pptr);
  for(int i = 0; i < num_parameters; i++){
      search_space-> parameters[i] = &parameters[i];
  }
  
  search_space->size = size;
  search_space->num_parameters = num_parameters;
  search_space->values = *pptr;
}

方案总结

不要用递归调用单路径遍历所有可能性,大部分工作可以交给while循环完成。这样就不会生成过多递归调用,导致函数执行完成前就耗尽内存。优化后递归深度最多控制在10层,运行正常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 03:39:00