3

main()ブロックで宣言された 2D ジャグ配列があります。これは関数に渡され、メモリが割り当てられます。以下は、コンパイルはできるが実行時にクラッシュする最も縮小されたケースです。どこが間違っていますか?

#include <stdio.h>
#include <stdlib.h>

void alloc2d(double ***p);


int main () {

    double **data;

    alloc2d(&data);
    printf("Before assign to data\n");
    data[0][0] = 0.1;
    printf("After assign to data\n");
    free(data);
}


void alloc2d(double ***p) {

    int i, n, m;

    // Get some dynamically assigned sizes
    printf("Enter size: ");
    scanf("%d %d", &n, &m);    
    // Now allocate
    *p = malloc(n * sizeof(double*));
    for (i = 0; i < n; i++) {
        *p[i] = malloc(m * sizeof(double));
    }
    printf("End of alloc2d\n");
}

これは値を読み取りますが、小さい数値 (つまり「1 1」) を入力するとクラッシュしますが、大きい数値 (つまり「10 10」) を入力するとクラッシュします。

4

3 に答える 3

7

非常に単純な構文エラーを犯しました

*p[i] = (double*)malloc(m * sizeof(double));

本当にあるべき

(*p)[i] = (double*)malloc(m * sizeof(double));

これは、C では [] 演算子の優先順位が * よりも高いためです。したがって、 と入力*p[i]すると、 に変換され**(p + i)ます。

これは、 p のアドレスを でオフセットしてアドレスを計算するようコンパイラーに要求していることを意味しますi * sizeof(double**)。これは明らかに実際に必要なものではありません。

したがって、コンパイラに最初に p を逆参照させるには、単純*pに括弧で囲みます。

于 2012-10-18T15:52:22.037 に答える
3

演算子の優先順位が答えです。*p[i]と同等*(p[i])です。これにより、ポインタの直後にあるメモリにアクセスできるようdataになり、スタック上の他の変数が破損するか、完全にクラッシュします。

を探していましたが(*p)[i]、これは新しく割り当てられた配列の i 番目のエントリになります。

于 2012-10-18T15:54:10.377 に答える
0

alloc2d() が割り当てるものは、実際には 2D 配列ではありませんが、次のとおりです。

  • 1 double へのポインターの 1D n-long 配列
  • n double の 1D m 長配列

C での多次元配列は、コンパイル時に最後の次元を除くすべての次元がわかっている場合にのみ可能です。

double a[5][11];

多分、このプログラムはあなたが理解するのを助けることができます... 行がランタイム変数であっても、COLUMNS がコンパイル時の定数であることに注意してください:

#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <err.h>

typedef double  myrow_t[11]; /* 11 columns */
#define COLUMNS (sizeof(myrow_t)/sizeof(double))

static unsigned
alloc2d(myrow_t **pd)
{
unsigned int rows;

printf("Enter the number of rows: ");
while (scanf("%u", &rows) != 1)
    printf("\ninvalid input, please, try again: ");

*pd = malloc(rows * sizeof(**pd));
if (*pd == NULL)
    err(EX_TEMPFAIL, "Out of memory");

return rows;
}

int
main()
{
myrow_t     *d;
unsigned int     row, column, rows;

rows = alloc2d(&d);

for (row = 0; row < rows; row++)
    for (column = 0; column < COLUMNS; column++)
        d[row][column] = row * column;

for (row = 0; row < rows; row++) {
    printf("Row %3d:\t", row);
    for (column = 0; column < COLUMNS; column++)
        printf("%.0f\t", d[row][column]);
    puts("");
}

free(d);
return 0;
}
于 2012-10-18T21:47:18.757 に答える