C. Ошибка сегментации, когда функция изменяет динамически размещенный 2d массив - PullRequest
2 голосов
/ 17 декабря 2009

Что мне нужно, это функция, которая модифицирует данный указатель на 2d матрицу следующим образом:

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);
      }
   }
}

Почему я получаю ошибку?

Ответы [ 3 ]

6 голосов
/ 17 декабря 2009

Тестовая матрица все еще 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);
      }
   }
}
2 голосов
/ 17 декабря 2009

Поскольку изменение матрицы внутри intMatrixAll () не изменяет testMatrix в main (). Если вы хотите изменить переменную main, вам нужно передать на нее указатель. Поэтому вам нужно изменить intMatrixAll на:

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

Внутри intMatrixAll теперь вам нужно изменить matrix на *matrix (а для индексации вам понадобится (*matrix)[...].

Наконец, вам нужно изменить свой вызов intMatrixAll на:

intMatrixAll(testArrRow, testArrCol, &testMatrix);

Причина в том, что C поддерживает только передачу по значению, а передача по значению не поддерживает вызываемую функцию, изменяющую значение переменной в вызывающей стороне.

Чтобы изменить значение переменной в вызывающей программе, вам нужно передать указатель на переменную, а затем вызвать вызываемую функцию, разыменовать ее.

0 голосов
/ 17 декабря 2009

Пожалуйста, смотрите здесь для обсуждения чего-то подобного. Причина, по которой он вызывает ошибку, заключается в том, что вы не передаете указатель на указатель на int из функции intMatrixAll в основную подпрограмму. Другими словами, вы передаете параметр двойного указателя на int по значению , а не по reference и пытаетесь получить доступ к testMatrix, хотя на самом деле он все еще был NULL .

Таким образом, вам нужно добавить еще один уровень косвенности, то есть *, и использовать эту косвенность в качестве средства для изменения двойных указателей на malloc d и для основной процедуры, чтобы увидеть, что testMatrix действительно выделен ,

См. Ответ Р. Самуэля Клатчко выше.

Как правило, если вы хотите передать указатель на что-либо как параметр по ссылке , добавьте еще один уровень косвенности. В вашем случае вы передаете двойной указатель на int, сделаете параметр тройным указателем в функции.

int **testMatrix;
void intMatrixAll(int row, int col, int ***matrix){
  // In here use this (*matrix)
}

// Then the calling of the function would look like this
intMatrixAll(testArrRow, testArrCol, &testMatrix); 

// Note the ampersand above to treat this double pointer passed in by reference

Надеюсь, что это помогает и имеет смысл, С наилучшими пожеланиями, Том.

...