【问题标题】:C. Segmentation Fault when function modifies dynamically allocated 2d arrayC. 函数修改动态分配的二维数组时出现分段错误
【发布时间】:2010-12-27 10:47:00
【问题描述】:

我需要一个函数来修改给定的指向二维矩阵的指针,如下所示:

void intMatrixAll(int row, int col, int **matrix);

现在,函数应该分配内存并且可以使用矩阵。行和列在运行时给出。

#include <stdio.h>
#include <stdlib.h>
#define PRINTINT(X) printf("%d\n", X);
void intMatrixAll(int row, int col, int **matrix);

int main(void) {
   int testArrRow = 4;
   int testArrCol = 6;
   int **testMatrix = NULL;
   intMatrixAll(testArrRow, testArrCol, testMatrix);
   testMatrix[2][2] = 112; //sementation fault here :(
   PRINTINT(testMatrix[2][2]);
   system("PAUSE");
   return 0;
}

void intMatrixAll(int row, int col, int **matrix) {
   printf("intMatrixAll\n");
   //allocate pointers:
   matrix = malloc(row * sizeof(int *));
   if(matrix == NULL) printf("Failed to allocate memmory.\n");
   for(int i=0; i<row; i++) {
      //allocate space for cols: 
      matrix[i] = malloc(col * sizeof(int));
      if(matrix[i] == NULL) {
         printf("Failed to allocate memmory for arr[%d].\n", i);
         exit(0);
      }
   }
}

为什么会出错?

【问题讨论】:

  • 我很确定您需要返回指向数组的指针,或者接收指向数组的指针(***int 矩阵,或者更易读的 *matrix[][] )

标签: c arrays memory pointers


【解决方案1】:

测试矩阵仍为 NULL。您需要从 intMatrixAll() 返回新分配的指针。要么从函数中返回值,要么传入 testMatrix 的地址以便设置。

#include <stdio.h>
#include <stdlib.h>
#define PRINTINT(X) printf("%d\n", X);
void intMatrixAll(int row, int col, int **matrix);

int main(void) {
   int testArrRow = 4;
   int testArrCol = 6;
   int **testMatrix = NULL;
   intMatrixAll(testArrRow, testArrCol, &testMatrix);
   testMatrix[2][2] = 112; //sementation fault here :(
   PRINTINT(testMatrix[2][2]);
   system("PAUSE");
   return 0;
}

void intMatrixAll(int row, int col, int ***matrix) {
   printf("intMatrixAll\n");
   //allocate pointers:
   *matrix = malloc(row * sizeof(int *));
   if(*matrix == NULL) printf("Failed to allocate memmory.\n");
   for(int i=0; i<row; i++) {
      //allocate space for cols: 
      *matrix[i] = malloc(col * sizeof(int));
      if(*matrix[i] == NULL) {
         printf("Failed to allocate memmory for arr[%d].\n", i);
         exit(0);
      }
   }
}

【讨论】:

  • 返回 int ** 比采用 int *** 参数更好。
【解决方案2】:

因为在 intMatrixAll() 中修改矩阵不会在 main() 中修改 testMatrix。如果您希望能够修改 main 的变量,则需要传递一个指向它的指针。所以你需要将 intMatrixAll 更改为:

void intMatrixAll(int row, int col, int ***matrix)

在 intMatrixAll 中,您现在需要将 matrix 更改为 *matrix(当您对其进行索引时,您需要 (*matrix)[...]

最后,您需要将对 intMatrixAll 的调用更改为:

intMatrixAll(testArrRow, testArrCol, &testMatrix);

原因是C只支持传值,传值不支持被调用函数在调用者中改变变量的值。

为了在调用者中修改变量的值,你需要传递一个指向变量的指针,然后让被调用的函数取消引用它。

【讨论】:

  • 这行得通!谢谢塞缪尔!所以我需要用 * 取消引用矩阵 arg ...我忘记了按值传递和按引用传递规则。我认为这仅适用于变量,不适用于指针。
  • testMatrix 一个变量。
  • 该死!我的意思是基本的 C 数据类型,如 int 和 char。所以我明白,当你传递一个指向函数的指针时,你实际上是通过引用传递的。错误的。谢谢。
  • @Martin - 起初它令人困惑,因为您使用指针来模拟按引用传递(即,如果您想通过引用传递 int,则使用指向 int 的指针)。但在所有情况下,实际参数始终是按值传递的。
  • 嘿山姆,你能再帮我点忙吗?我以为我理解了这个 (*matrix)[...] 部分,但我没有:( 我用它来打印函数中的值:PRINTINT((*m1)[1][3]); 我认为它是与 *(*(*(m1+1)+3)) 相同,那么 (*m1)[1][3] 到底是什么?更准确地说,为什么是 (*m1),为什么不只是 *m1[1][3] ??
【解决方案3】:

请参阅here 以讨论类似问题。它出现段错误的原因是因为您没有将 int 的指针的指针从函数intMatrixAll 传回主例程。换句话说,您将双指针的参数传递给 int 的按值,而不是按引用,并尝试访问testMatrix,而实际上它仍然是@ 987654324@.

因此,您需要添加另一个级别的间接,即*,并使用该间接将双指针更改为mallocd,并让主例程看到testMatrix 确实已被分配.

见上面 R. Samuel Klatchko 的回答。

作为一般规则,如果您想通过引用将指针作为参数传递,请添加另一个间接级别。在您的情况下,您传入一个指向 int 的双指针,将参数作为函数中的三重指针。

int **testMatrix; void intMatrixAll(int row, int col, int ***matrix){ // 在这里使用 this (*matrix) } // 那么函数的调用应该是这样的 intMatrixAll(testArrRow, testArrCol, &testMatrix); // 注意上面的&符号来处理这个通过引用传入的双指针

希望这会有所帮助并有意义, 最好的祝福, 汤姆。

【讨论】:

  • 是的,这个方法和 Samuel 一样有效。感谢您的详细解释。要问你一些事情,你或这里的其他人是否知道一些我可以深入学习指针的书籍或网站。我在网络上创建的所有内容都是初学者级别的指针,我很想学习它们。你知道,这本书会解释这个 int *(*list[ MAX ])();和类似的创伤。
  • @Martin Berger:我不知道它是否仍在印刷中,但请尝试 amazon.com - Peter Van Der Linden 的“Expert C Programming - Deep C Secrets”。很棒的东西——读它,活它,呼吸它,吃它!!! ;)
  • @tommieb75:就是这样!指针、内存分配和编译。并且深入!求推荐!
  • @Martin Berger:太好了!请推荐其他人偶然发现指针等去购买这本书 - 它是 100% 值得的,并且会让你精通 C! ;)
猜你喜欢
  • 1970-01-01
  • 2011-07-28
  • 2021-03-25
  • 2021-08-04
  • 2013-09-04
  • 1970-01-01
  • 2018-06-16
  • 1970-01-01
  • 2016-11-28
相关资源
最近更新 更多