以前の質問(Jonathan Lefflerに感謝します)のように、コード(2番目の2ブロックのコード)を編集しましたが、かなり奇妙な問題が発生しました。
次のものは予期せず壊れます...
void free_array(array_info *A)
{
int i;
for(i = 0; i < (A->height); ++i)
{
printf("About to free: %x\n", A->dat_ptr[i]);//for debugging purposes
free(A->dat_ptr[i]);
printf("Freed row %i\n", i);//for debugging purposes
}
free(A->dat_ptr);
}
私は最初にcreate_array
直接テストした後free_array
、かなり大きなアレイ(10 ^ 8)で問題なく動作しました。ただし、その間に計算を行ってからfree()
配列を試してみると、アクセス違反の例外(c00000005)が発生します。デバッグしているときに、「free_array」ループ内にブレークポイントがあり、すべての行を個別に実行すると、プログラムが毎回完全に実行されることに気付きました。ただし、コンパイルされたコードは、それ自体では2番目の配列のrow6を超えて実行されることはありません。コンパイラですべての最適化をオフにしましたが、実行時にエラーが発生しました。
追加情報
typedef struct {
int height;
int width;
int bottom;//position of the bottom tube/slice boundary
unsigned int** dat_ptr;//a pointer to a 2d array
} array_info;
ここで、dat_ptr
は適切な2Dポインタになります。create_array
構造体に配置される配列を作成する関数は次のとおりです(読みやすさのためにNULLチェックを削除しました)。
int create_array(array_info *A)
{
int i;
unsigned int **array = malloc(sizeof(*array) * A->height);
for (i = 0; i < A->height; ++i)
{
array[i] = malloc(sizeof(**array) * A->width);
}
A->dat_ptr = array;
return 0;
}
この関数は期待どおりに機能します。
詳細追加情報
ジョナサン、クリス、ラリソンの回答の後に追加33
ジョナサン、ありがとうございました。あなたの投稿のすべてで、プログラミングについて多くのことを知りました:)ついに犯人を見つけました。例外の原因となったコードは次のとおりです。
void fill_number(array_info* array, int value, int x1, int y1, int x2, int y2)//fills a rectangular part of the array with `value`
{
int i, j;
for(i=y1 ; ((i<=y2)&&(i<array->height)) ; i++)//start seeding the values by row (as in vertically)
{
for(j=x1 ; ((i<=x2)&&(i<array->width)) ; j++)//seed the values by columns (as in horizontally)
{
array->dat_ptr[i][j]=value;
}
}
}
そして((i<=x2)&&(i<=array->width))
、私が期待したように評価されていませんでした(クリス・ドッド、あなたは正しかったです)。両方の条件をその順序で評価するか、順序に関係なくどちらかが「FALSE」の場合は停止すると思いました。(i<array->width)
しかし、それはそのようには機能せず、部品を正しく評価することを単に拒否していたことが判明しました。また、配列範囲外のメモリにアクセスしようとすると例外が発生すると思いましたが、発生しませんでした。ともかく、
コードを次のように変更しました。
void fill_number(array_info* array, int value, int x1, int y1,
int x2, int y2)
{
int i, j;
if(y1>=array->height){ y1=array->height-1;}
if(y2>=array->height){ y1=array->height-1;}
if(x1>=array->width) { x2=array->width-1;}
if(x2>=array->width) { x2=array->width-1;}
for(i=y1 ; i<=y2 ; i++)//start seeding the values by row
{
for(j=x1 ; j<=x2 ; j++)//seed the values by column
{
array->dat_ptr[i][j]=value;
}
}
}
そして今、それは機能します。sのブロックはif()
、他のコードと比較して関数を頻繁に呼び出さないためにあり、チェックがそこにあることを視覚的に思い出させる方法が必要です。
繰り返しになりますが、ジョナサン・レフラー、クリス・ドッド、そしてラリソンに感謝します33 :)