2012-02-03 4 views
3

私のプログラムでは小さなメモリアクセスの問題があり、エラーが見つからない場合は、誰かが助けてくれるかもしれません。2Dアレイに書き込むことによるセグメンテーションフォールト

rgbの色の値を格納する新しいタイプを作成しました。 そのタイプは、次のようになります。私は、のcallocと2次元動的配列を作成し、赤の色情報のを保存するために私のメインプログラムでは

typedef struct pixel { 
    unsigned char r; 
    unsigned char g; 
    unsigned char b; 
} pixel; 

pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); 
for (i = 0; i < imginformation.width; i++) { 
    pixelvalue[i] = (pixel *) calloc(imginformation.height, sizeof(pixel)); 
} 

その後、私は色の値を読み取って、それらを安全にする必要がある私の関数を呼び出します。この関数は配列としてパラメータを取得します。その関数で

ReadFile(file, imginformation (Stuff like height and so one), pixelvalue (The calloc array)); 

私は

pixelvalue[i][j].r = (unsigned char)fgetc(in); 

に値を書き込むしようとここで私は私が間違って何をしたか、メモリアクセスエラーを取得しますか?

編集

こんにちは、不足している言語に関するすべて申し訳ありませんの最初、私は昨日、少し疲れていた:)。

私はピクセルの配列を作成し、その要素はピクセルの別の配列を指していますか? [Point to another 1D array pixel]のようなもの?

ピクセルの場合**pixelvalue = calloc(imginformation.width, sizeof(pixel *));imginformation.widthタイプのピクセルからポインタの番号を作成し、ピクセルごとに表示します。

私が間違っていれば、もう少し説明できたらすばらしいと思います。私は本当にそれを理解したいと思います。カール・norum @

あなたが何を意味するか:。

を「あなたはのcallocの戻り値をキャストするべきではありません()ので、噛まないように戻ってくる可能性の#includeと 非表示のバグをすることができます行いますあなたは 道路を下りました。 "

?関数の戻り値ではなくパラメータとしてalloc空間を使用します。

ありがとうございました!

Greetz

答えて

3

あなたは本当にあなたがピクセルの配列を指すポインタの配列を作っている、2次元配列を行っていません。それはあなたの最初のcalloc呼び出しはポインタのためではなく、ピクセルのための十分なスペースを割り当てる必要があります意味:

pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 

あなたは言語にあなたの質問にタグを付け、それはないだろう、あなたのtypedefに基づいてC(、だと仮定していませんでしたC++で必要です)、戻り値はcalloc()です。そうすることで、道路に噛み付くように戻ってくるかもしれない#includeのバグを隠すことができます。

編集:

あなたは、フォローアップの質問のカップルを尋ねました。最初のものはいくつかの他の答えによってかなりうまく答えられていると私は思いますが、私は要約しようとします。あなたが割り当てをやっているところでは、まずポインタの配列を割り当てます。ポインタは配列の1つの行を指しています。次に、行自身が割り当てられる必要があります。各オブジェクトのスペースはそこにあり、行のポインタはポインタの最初の配列に格納されます。

あなたの2番目の質問は、戻り値calloc()からはかなり簡単です。戻り値をキャストすると、暗黙の宣言バグを自分自身に隠すことができます。 callocの戻り値の型は、void *あるので、あなたのような何かをする場合:

my_ptr = calloc(1, 2); 

すべてがうまく動作します。今度はstdlib.hが含まれていないため、翻訳単位にcalloc()というプロトタイプがないとします。コンパイラがcalloc()の署名をint calloc(int, int)と仮定することになりますが、これは真実ではありません。上のコードと同じ行では、その関数のデフォルトの署名を前提とした警告が表示されます。コード内にあるような型キャストを使用すると、その警告が隠され、#include行が見つからないことは決して分かりません。あなたのtypedef -

+0

、感謝あなたのソリューションが正常に動作します。今私はいくつかの問題を理解している、私は編集を参照してください。ありがとう。 – hofmeister

+0

@ Taz - あなたの変更を一時的に解決するように編集します。 –

0

コード

pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); 

pixelvalueはピクセルへのポインタへのポインタです。

代わり

pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 

を記述する必要があります。

+0

よろしくお願いします。@ carl-norum。私を見てください**編集**、私はそれを正しく理解しましたか? – hofmeister

1

ですから、最初のcallocを使用してpixel *の配列を作成し、について説明enter image description here

ための図を参照してください。その配列にcallocpixelを入力します。

+0

ありがとう、それは多くの助けになりました!だから、まず、すべてのポインタを作成します。たとえば、高さとすべての要素が幅のピクセルに表示されます。ありがとうございました! – hofmeister

+0

Taz - あなたの心の中で物事を合理化するためにダイアグランを使うのが助かります –

0

他のポスターは、pixelの代わりに、pixel*の単位で最初のメモリブロックを割り当てる必要があることを正しく認識しています。

しかし、なぜこの問題がsegfaultを引き起こしますか?

32ビットマシンでは、上記で定義したピクセル構造体は3バイト必要ですが、ポインタは32ビット(4バイト)をとります。

だから、あなただけのあなたが必要とするメモリの75%を配分している

  • sizeof(pixel) == 3
  • しかしsizeof(pixel*) == 4

、です。画像の下半分にアクセスすると、割り当てられなかったメモリにアクセスします。

(一部の64ビットプラットフォームでは、この問題は間違いなく悪化します。こんにちは、いくつかの16ビットプラットフォームでは、それはまだずさんになるだろうが、あなたは、これで逃げることができるかもしれません)

+0

しかし、私はピクセルのポインタを使っても問題ないですか? – hofmeister

+0

はい、する必要があります。なぜこの問題が発生しているのか理解しています。 (エドヒールの細かい図を参照) –

+0

はい、私はしました。皆さん、ありがとうございました! – hofmeister

関連する問題