![](/img/trans.png)
[英]C - Pointer to dynamic array in struct “Segmentation fault (core dumped)”
[英]C - Segmentation Fault Reading Struct and Dynamic2D Array Member
我剛開始學習 C,我想嘗試創建一個適用於指針、結構和 arrays 的測試程序,因為我仍然很難理解它們。 我創建了這個測試文件,它是我正在處理的一個更大項目的精煉版本。 測試文件有一個結構體,其中包含一個動態二維數組作為結構體的成員:
typedef struct {
int ** array;
int rows, cols;
} Smaller;
但是,運行測試文件后,終端返回以下錯誤:
zsh: segmentation fault ./a.out
我研究了這個錯誤的含義,
" 分段錯誤是訪問“不屬於您”的 memory 導致的一種特定錯誤。 “ ( 鏈接)
但我仍然對如何解決這個問題感到困惑。 我很確定我為每一行和每一列分配了正確數量的 memory。 這更加令人困惑,因為終端沒有指示錯誤是哪一行。 我將不勝感激有關此問題的任何幫助。
以下是完整代碼:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int ** array;
int rows, cols;
} Smaller;
void printArray (Smaller * s);
int main () {
int x, i, j;
Smaller * sand;
// allocate mem for number of rows
sand->array = malloc (3 * sizeof(int *));
//allocate mem for number of columns
sand->array = malloc(4 * sizeof(int));
sand->array = malloc(4 * sizeof(int));
sand->array = malloc(4 * sizeof(int));
// adding a constant value to the 2D array
for (i = 0; i < 3; i ++) {
for (j = 0; j < 4; j ++) {
sand->array[i][j] = 6;
}
}
printArray(sand);
return 0;
}
void printArray (Smaller * sand) {
printf("Welcome to the printArray function! \n");
int i, j;
for (i = 0; i < 3; i ++)
for(j = 0; j < 4; j ++)
printf("array[%d][%d] = %d \n", i, j, sand->array[i][j]);
}
問題是,正如@tromgy 指出的那樣,您正在用列 arrays 覆蓋基礎 sand- sand->array
而不是將它們分配給它。 正確的代碼如下所示:
#include <stdlib.h>
#define NUM_ROWS 3
#define NUM_COLS 4
typedef struct {
int ** array;
int rows;
int cols;
} Smaller;
void print_array(Smaller * s);
int main(void) {
Smaller * sand = malloc(sizeof(Smaller));
if (!sand) return -1; /* allocation failed, abort */
sand->rows = NUM_ROWS;
sand->array = malloc(sizeof(int*[NUM_ROWS]));
if (!sand->array) { /* allocation failed, abort */
free(sand); /* free sand first, though */
return -1;
}
for (size_t i = 0; i < NUM_ROWS; ++i) {
sand->array[i] = malloc(sizeof(int[NUM_COLS]));
if (!sand->array[i]) {
/* free the previous rows */
for (size_t j = 0; j < i; ++j) free(sand->array[j]);
free(sand->array);
free(sand);
return -1;
}
}
/* add a constant value to the array */
for (size_t i = 0; i < NUM_ROWS; ++i) {
for (size_t j = 0; j < NUM_COLS; j ++) {
sand->array[i][j] = 6;
}
}
print_array(sand);
/* Ok, now free everything */
for (size_t i = 0; i < NUM_COLS; ++i) {
free(sand->array[i]);
}
free(sand->array);
free(sand);
/* NOW we may exit */
return 0;
}
如您所見,分配這樣的結構需要大量工作,並且您必須釋放分配的任何內容,因此最好將其提取到 function 中,例如Smaller * smaller_init(size_t nrows, size_t ncols)
和void smaller_destroy(Smaller * s)
封裝了所有的工作。
我將在下面留下一個示例,以便您可以將其與您最初編寫它的方式進行比較...
關於您的代碼:
for
命令中聲明循環變量Smaller
不需要是指針struct
中設置rows
和cols
的值。 在main()
中不要像你那樣使用固定值 3 和 4row
+ column
...這樣您可以查看循環是否正常並且所有元素都正在打印。 請參閱此 output 的 printArray printArray()
: 0 1 2 3
100 101 102 103
200 201 202 203
每行都以行號開頭,因此您可以在繼續之前對其進行幾次測試。
printArray()
中顯示如下尺寸: printArray[3,4]
0 1 2 3
100 101 102 103
200 201 202 203
參見示例的 output
Smaller* freeArray(Smaller* A)
{
printf("\nfreeArray()\n");
for (int i = 0; i < A->rows; i++)
{
free(A->array[i]); // delete lines
printf("row %d free()\n", i);
}
free(A->array); // delete cols
printf("pointer to rows free()\n");
free(A); // delete struct
printf("struct free()\n");
return NULL;
}
這樣你就知道指針sand
不會指向一個已經free()
d 的區域。 使用這樣的指針會使你的程序崩潰,所以最好寫
sand = freeArray(sand);
printArray[3,4]
0 1 2 3
100 101 102 103
200 201 202 203
freeArray()
row 0 free()
row 1 free()
row 2 free()
pointer to rows free()
struct free()
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int** array;
int rows, cols;
} Smaller;
void fillArray(Smaller*);
Smaller* freeArray(Smaller*);
Smaller* makeArray(size_t, size_t);
void printArray(Smaller*);
int main(void)
{
int y = 3;
int x = 4;
// sand points to a Smaller
Smaller* sand = makeArray(y, x);
// adding known unique values to cells is easier
fillArray(sand);
printArray(sand); // show values
sand = freeArray(sand); // delete all
return 0;
}
void fillArray(Smaller* A)
{
for (int i = 0; i < A->rows; i++)
for (int j = 0; j < A->cols; j++)
A->array[i][j] = 100 * i + j;
}
Smaller* freeArray(Smaller* A)
{
printf("\nfreeArray()\n");
for (int i = 0; i < A->rows; i++)
{
free(A->array[i]); // delete lines
printf("row %d free()\n", i);
}
free(A->array); // delete cols
printf("pointer to rows free()\n");
free(A); // delete struct
printf("struct free()\n");
return NULL;
}
Smaller* makeArray(size_t y, size_t x)
{
// sand points to a Smaller
Smaller* sand = (Smaller*)malloc(sizeof(Smaller));
sand->rows = y;
sand->cols = x;
// allocate mem for number of rows, that is 'y'
sand->array = malloc(y * sizeof(int*));
// allocate mem for each of the 'x' columns
for (size_t i = 0; i < y; i++)
sand->array[i] = malloc(x * sizeof(int));
return sand;
};
void printArray(Smaller* sand)
{
printf("printArray[%d,%d]\n\n", sand->rows, sand->cols);
for (int i = 0; i < sand->rows; i++)
{
for (int j = 0; j < sand->cols; j++)
printf("%3d ", sand->array[i][j]);
printf("\n");
}
}
請所以人們不要費心指出我不要投射malloc()
的結果。 這是由決定。 這個常見的建議是對 90 年代 C-faq 的回憶,現在我們知道隱式轉換可能不太好。 事實上,隱含的事情可能會花費你很多時間:如果你malloc()
程序中的一系列不同結構並省略類型,如果其中一些是相反的,請記住,使用所有強制轉換將幫助你避免這種代價高昂的錯誤...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.