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

C++中返回二维数组时如何避免Segmentation Fault?

问题描述

这是一门C++入门课程的作业任务:在二维数组matrix中查找两个数之和等于给定值search_sum的所有组合,将找到的加数组合以{startRow,startColumn,endRow,endColumn}的形式存入summations数组,最终返回该数组。

我尝试用语句summations[*sums_found]={startRow, column, endRow, column};给已分配的内存赋值时,触发了“too many assignments”和段错误(Segmentation Fault)。移除这条赋值语句后运行代码,还是会出现段错误。

我的困惑:

  1. 这段代码是用来分配内存写入数据的,为什么会触发和只读相关的段错误?
  2. 该如何正确为summations数组赋值?
  3. 需要重点学习哪些C++知识点来解决这类问题?

当前代码如下:

// Parameters:
//  - matrix: a two-dimension integer array
//  - matrix_size: a two-element size_t array storing sizes of matrix
//  - search_sum: the integer value for which the function seeks sums
//  - sums_found: an OUTPUT PARAMETER pointing to a size_t
//
const size_t** FindSum(const int** matrix,
                       const size_t* matrix_size,
                       int search_sum,
                       size_t* sums_found) {
  *sums_found = 0;  // init sums found to 0

  size_t summations_size = 2;  // start assuming no more than 2 summations
  // build structure to hold all found summations
  size_t** summations = new size_t*[summations_size];

  switch (search_sum)
  {
  case -92:{ //column search 
    
    for(size_t column = 0; column < matrix_size[1]; column++){
        for(size_t startRow = 0; startRow < matrix_size[0]; startRow++){
            for(size_t endRow = 0; endRow < matrix_size[0]; endRow++){
              int j = matrix[startRow][column];
              int k = matrix[endRow][column];
              int sum = j + k;
              if(sum = search_sum){
                  summations[*sums_found] = new size_t[kIndices_size]; // only done when summation is found
                  *sums_found++; 
              }
            }
        }
      }
  }
    
    break;
  case 60:{ //row search
    for(size_t row = 0; row < matrix_size[0]; row++){
        for(size_t startColumn = 0; startColumn < matrix_size[1]; startColumn++){
            for(size_t endColumn = 0; endColumn < matrix_size[1]; endColumn++){
              int j = matrix[row][startColumn];
              int k = matrix[row][endColumn];
              int sum = j + k;
              if(sum = search_sum){
                  summations[*sums_found] = new size_t[kIndices_size]; // only done when summation is found
                    *sums_found++; 
              }
            }
        }
      }
  }
  break;
  case 1203:{ //desc/ascending diagonal

  }
  break;
  case 412:{ //single entry 

  }
  break;
  
  default:{ //large array

  }
    break;
  }
       
  return const_cast<const size_t**>(summations);
}
问题分析与解决

1. 段错误的触发原因

你的代码里有几个致命错误直接导致了段错误:

  • 赋值代替比较:if(sum = search_sum)是赋值操作,不是比较逻辑。这会把search_sum的值强制赋给sum,条件永远为真(除非search_sum是0),导致*sums_found不断递增,很快超过初始化的summations_size=2,访问summations[*sums_found]时直接越界,触发段错误。
  • 未定义变量kIndices_size:代码中使用了kIndices_size但从未定义或初始化,分配内存时会用随机值,可能分配异常大的内存导致耗尽,或者分配后访问越界。
  • 内存越界访问:即使kIndices_size是正确值(比如4,对应每个组合的4个坐标),当找到的组合数超过summations_size=2时,summations[*sums_found]会访问超出new size_t*[summations_size]分配的内存范围,直接触发段错误。

2. 正确为summations数组赋值的方法

按以下步骤修改代码:

  1. 先定义kIndices_size为4,因为每个组合需要存储{startRow, startColumn, endRow, endColumn}四个值。
  2. 把条件判断里的=改成==,确保是比较操作。
  3. 每次找到符合条件的组合时,先检查当前找到的数量是否超过summations_size,如果超过就扩容(重新分配更大的数组,拷贝旧数据后替换原数组)。
  4. 分配内存后,逐个给数组元素赋值(C++中不能直接用大括号给动态分配的数组赋值)。

修改后的示例片段(以column search为例):

// 先定义常量,明确每个组合的元素数量
const size_t kIndices_size = 4;

// ...

case -92:{ //column search 
    for(size_t column = 0; column < matrix_size[1]; column++){
        for(size_t startRow = 0; startRow < matrix_size[0]; startRow++){
            for(size_t endRow = 0; endRow < matrix_size[0]; endRow++){
                int j = matrix[startRow][column];
                int k = matrix[endRow][column];
                int sum = j + k;
                if(sum == search_sum){ // 修正为比较运算符
                    // 检查是否需要扩容
                    if (*sums_found >= summations_size) {
                        size_t new_size = summations_size * 2;
                        size_t** new_summations = new size_t*[new_size];
                        // 拷贝旧数据到新数组
                        for (size_t i = 0; i < summations_size; i++) {
                            new_summations[i] = summations[i];
                        }
                        // 释放旧数组内存
                        delete[] summations;
                        summations = new_summations;
                        summations_size = new_size;
                    }
                    // 分配内存并逐个赋值
                    summations[*sums_found] = new size_t[kIndices_size];
                    summations[*sums_found][0] = startRow;
                    summations[*sums_found][1] = column;
                    summations[*sums_found][2] = endRow;
                    summations[*sums_found][3] = column;
                    (*sums_found)++; // 加括号确保先取值再递增
                }
            }
        }
    }
}
break;

3. 需要重点学习的C++知识点

  • 动态内存管理:掌握new/delete的用法,理解动态数组的创建、扩容与内存释放逻辑,清楚内存越界的危害。
  • 运算符区分:严格区分赋值运算符=和比较运算符==,避免这类低级逻辑错误。
  • 多维数组结构:理解二维动态数组(指针的指针)的内存结构,学会正确访问和操作其中的元素。
  • 错误排查技巧:学会用调试工具(如gdb)定位段错误的根源,熟悉段错误的常见触发场景(内存越界、访问空指针、未初始化变量等)。
  • 变量定义规范:确保所有使用的变量都已正确定义、初始化,避免未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:15:47