2

動的な比率でマトリックスを作成しようとしています。これを初期化するには、メモリの割り当てと初期化に使用しているコードを次に示します。

int **matrix;
//mem allocation
matrix=(int*)malloc(sizeof(int*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i]=(int)malloc(sizeof(int)*mat_h);
//init
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;

これは正常に機能します。質問は、short型の行列を作成しようとすると、initの最初のパスでセグメンテーションエラーが発生します。

これはC言語の問題ですか、それとも私は何か間違ったことをしていますか?

タイプの行列のコードshort

short **matrix;
//mem allocation
matrix=(short*)malloc(sizeof(short*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i]=(short)malloc(sizeof(short)*mat_h);
//init
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;

PS:コードを明確にするために、安全性チェック、インデックス変数、境界宣言を削除しました。

ありがとう、
アレックス

4

6 に答える 6

17

の戻り値のキャストmalloc()は無効です。それらは、最初のケースでは、そして2番目のケースではである必要がint**あります。int*short**short*

malloc()の戻り値をにキャストすると、返されshortたポインタは値に収まるように切り捨てられてshortから、ポインタに割り当てられshort*、無効なメモリ位置を指すポインタ値が生成されます。したがって、アクセスしようとするとセグメンテーション違反が発生します。

を使用intすると、プラットフォーム上でおそらくが幸運になります。そのため、 casted tosizeof(int)==sizeof(int*)によって返されるポインタは切り捨てられず、すべてサイレントに機能します。64ビットプラットフォームでも同様の方法でクラッシュする可能性があります。malloc()int

する必要があります:

short **matrix;
matrix=(short**)malloc(sizeof(short*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i]=(short*)malloc(sizeof(short)*mat_h); 
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;

void*コードが純粋なC(C ++ではない)の場合、他のポインター型へのCキャストが有効であるため、キャストを省略できます。

short **matrix;
matrix = malloc(sizeof(short*)*mat_w);
for (i=0;i<mat_w;i++)
    matrix[i] = malloc(sizeof(short)*mat_h); 
for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        matrix[i][j]=0;
于 2009-10-12T12:27:33.993 に答える
15

これらの明らかなエラーすべてについて悲鳴を上げないように、どのコンパイラを使用していますか?

gcc -Wallこのコードで5つの警告メッセージを生成しました。

#include <stdlib.h>

int main ()
{
    int mat_w = 99;
    int mat_h = 666;
    int i;
    int j;

    int **imatrix;
    short **smatrix;
    //mem allocation
    imatrix=(int*)malloc(sizeof(int*)*mat_w);
    for (i=0;i<mat_w;i++)
    imatrix[i]=(int)malloc(sizeof(int)*mat_h);
    //init
    for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        imatrix[i][j]=0;

    //mem allocation
    smatrix=(short*)malloc(sizeof(short*)*mat_w);
    for (i=0;i<mat_w;i++)
    smatrix[i]=(short)malloc(sizeof(short)*mat_h);
    //init
    for (i=0;i<mat_w;i++)
    for (j=0;j<mat_h;j++)
        smatrix[i][j]=0;
    return 0;
}

私にくれ

malloc.c: In function 'main':
malloc.c:13: warning: assignment from incompatible pointer type
malloc.c:15: warning: assignment makes pointer from integer without a cast
malloc.c:22: warning: assignment from incompatible pointer type
malloc.c:24: warning: cast from pointer to integer of different size
malloc.c:24: warning: assignment makes pointer from integer without a cast
于 2009-10-12T12:35:15.743 に答える
6

この間違いから学ばなければならない重大な教訓があります。そしてそれは次のように言っています:'malloc'の結果をキャストしないでください。

さらに、これは、可能な限り従うのが最善の、より大きな実践的な基準の一部です。宣言を除いて、コードで型名を言及しないでください

これは、コードが最初からどのように見えるべきかを示しています。

  int **matrix;

  matrix = malloc(mat_w * sizeof *matrix);
  for (i = 0; i < mat_w; i++)
    matrix[i] = malloc(mat_h * sizeof *matrix[i]);

  for (i = 0; i < mat_w; i++)
    for (j = 0; j < mat_h; j++)
      matrix[i][j] = 0;

このバージョンで「int」から「short」に切り替えるには、「matrix」の宣言を変更するだけでよいことに注意してください。

(もちろん、このコードで改善できることは他にもありますが、エラーの直接の理由に対処したかっただけです。)

于 2009-10-12T17:45:03.323 に答える
5

あなたはmallocの戻り値にキャストint**していますint*(略して同じです)。mallocこのように使用する必要があります:

matrix = (int**)malloc(sizeof(int*) * mat_w);

また

matrix = (short**)malloc(sizeof(short*) * mat_w);

マトリックス内の各割り当てについて同じ:

matrix[i] = (int*)malloc(sizeof(int) * mat_h);

また

matrix[i] = (short*)malloc(sizeof(short) * mat_h);
于 2009-10-12T12:28:01.450 に答える
2

はい、あなたは何か間違ったことをしています。

 int *matrix;

matrixは整数の配列であることを意味します。整数の配列の配列にしたい場合は、次のように宣言する必要があります。

 int **matrix;
 //mem allocation
 matrix=(int**)malloc(sizeof(int*)*mat_w);
 for (i=0; i<mat_w; i++)
     matrix[i]=(int*)malloc(sizeof(int)*mat_h);
 //init
 for (i=0; i<mat_w; i++)
     for (j=0; j<mat_h; j++)
         matrix[i][j]=0; 

もちろん、行列の次元を事前に知っている場合は、次のようにしてください。

int matrix[mat_w][mat_h];
 //init
 for (i=0; i<mat_w; i++)
     for (j=0; j<mat_h; j++)
         matrix[i][j]=0; 
于 2009-10-12T12:29:52.617 に答える
0

sizeof(int)特定のシステムのバス幅に等しい。32ビット(またはプラットフォームによっては64)のアドレス値を16ビットの割り当てられたメモリに入れようとしています。

チェッカーの投稿の2番目の例を確認してください。これは、メモリ割り当ての正しくて好ましい方法です。

于 2009-10-12T12:29:48.107 に答える