C言語関係掲示板

過去ログ

No.1178 mallocとポインタについて

[戻る] [ホームページ]
No.15358

mallocとポインタについて
投稿者---kkk(2004/07/09 01:41:20)


int load_pp_file(int **img, char*filename,int *width,int *height){
FILE *fp;

fp=fopen(filename,"r");
*img=(int*)malloc((*width)*(*height)*3);

とあって,
img[x]=0x00ff & fgetc(fp);

というようにしたのですが,BussError やSegmentation 違反になります.
ポインタの使い方が間違っているのはわかるのですが
これではだめなのでしょうか?


No.15360

Re:mallocとポインタについて
投稿者---あかま(2004/07/09 02:41:29)


>これではだめなのでしょうか?
何がしたいのか書かないと「だめ」の内容がわかりません。
コンパイルは通ればOKなだけなら「だめではない」でしょう。
実行時にエラーを出したくないのなら、セグメンテーションエラーがでるのですから「だめ」でしょう。

>ポインタの使い方が間違っているのはわかるのですが
使い方が間違っているのが分かるのなら直せばいいのですが。
2次元配列を動的に確保したいのなら過去ログを見てください。
違うのならやりたいことを書いてください。




No.15364

Re:mallocとポインタについて
投稿者---NykR(2004/07/09 08:56:45)


何となく想像はつきますが、

>img[x]=0x00ff & fgetc(fp);


xの値が(大体)どれくらいの時にSegmentation 違反やBussErrorになるかわかりますか?
そこから原因は想像できませんか?


No.15365

Re:mallocとポインタについて
投稿者---円零(2004/07/09 09:44:36)


>>img[x]=0x00ff & fgetc(fp);
>
>xの値が(大体)どれくらいの時にSegmentation 違反やBussErrorになるかわかりますか?
>そこから原因は想像できませんか?


なるほど。的確なヒントですね。
まあ本でもヘルプでもインターネットでも、
ほかの人が書いたmallocの使い方をじーっと眺めれば気付くはず。

ところで三原色を格納したい場合、三次元配列の方が良さそうに思えますね。


No.15366

Re:mallocとポインタについて
投稿者---NykR(2004/07/09 09:48:15)


>BussError

BusErrorですね。Bussだとバスとは表記しなさそう。標準的な表記はブッスとかになりそうな気がする。


No.15369

Re:mallocとポインタについて
投稿者---ニタチ(2004/07/09 11:08:41)


>int load_pp_file(int **img, char*filename,int *width,int *height){
>FILE *fp;
>
>fp=fopen(filename,"r");
>*img=(int*)malloc((*width)*(*height)*3);

>img[x]=0x00ff & fgetc(fp);

 img[x]に格納できるのはint*型であって、int型ではありません。
 *img、つまりimg[0]の指し示す先に代入しなければなりません。
 


No.15373

Re:mallocとポインタについて
投稿者---kkk(2004/07/09 12:55:25)


int load_pp_file(int **img, char*filename,int *width,int *height){
FILE *fp;
fp=fopen(filename,"r");

*img=(int*)malloc((*width)*(*height)*3);

for(x=0;x<(*width)*(*height)*3;x++)
* img[x]=( 0x00ff & fgetc(fp) );
あれから,かんがえて上のようにしたのですが
まだエラーが出てしまいます.
ポインタのポインタであるimgをどのように領域をとればいいのかが
いまいちわかりません.
*imgで領域をとって,imgのところでも個々に領域を確保するのかなあ
ともおもうのですが.
xの値がどのくらいまで
読み込まれているのわかりません.
また,このforループの前に時点のmallocのところでエラーが
でています.
アドバイスをよろしくおねがいします


No.15375

Re:mallocとポインタについて
投稿者---nop(2004/07/09 13:11:36)


>*img=(int*)malloc((*width)*(*height)*3);

img の型は?
って言うか、あなたがやりたいのは、

img=(int*)malloc((*width)*(*height)*3);

または

img=(int**)malloc((*width)*(*height)*3);

では?


No.15376

Re:mallocとポインタについて
投稿者---NykR(2004/07/09 13:45:05)


>xの値がどのくらいまで
>読み込まれているのわかりません.

読み込んだときにprintfでxの値を表示させるとわかります。
# 実際にはfprintf(stderr, ...)
# とか、デバッグ出力用のマクロを定義したり。


>また,このforループの前に時点のmallocのところでエラーが
>でています.
>アドバイスをよろしくおねがいします

ではそのエラーメッセージをそのまま貼り付けてください。
# 間違ってもエラーの内容を、メッセージを貼り付けることなしに説明だけで済ませようとしないように。
# あなたは違うかも知れませんが、時々そういうことをする人がいるので念のため。


No.15379

Re:mallocとポインタについて
投稿者---kkk(2004/07/09 18:26:10)


>
>>また,このforループの前に時点のmallocのところでエラーが
>>でています.
>>アドバイスをよろしくおねがいします
>
>ではそのエラーメッセージをそのまま貼り付けてください。
># 間違ってもエラーの内容を、メッセージを貼り付けることなしに説明だけで済ませようとしないように。
># あなたは違うかも知れませんが、時々そういうことをする人がいるので念のため。
部分的に
img =(int**)malloc((*width) * (*height) * 3);

(*img)[x] =( 0x00ff & fgetc(fp));
としたところ以下のエラーがでました

P6
640,480
255
ERRORExit 1
となっています.
mallocで領域を確保する前にppmファイルのMAGICと画像サイズ最大値を読み込んでいます.
そして、次にppmファイルから値を入れる領域を作るところでエラーになっていると思います.
僕がやりたいのは,ppmファイルを読み込むことで,
他の人が書いたC++のプログラムをCに変える作業をしています.
元のC++では、
(*img)=new int[(*width)*(*height)*3];
となっていて,
for(x=0;x<(*width)*(*height)*3;x++)
(*img)[x]=0x00ff&fgetc(fp);
となっています.
この部分をCに直そうとして
エラーがでてしまって.


No.15380

Re:mallocとポインタについて
投稿者---ぽこ(2004/07/09 18:34:23)


kkkさんが確保したメモリサイズと
C++の元ソースで確保しているメモリサイズが違う気がしますが。。

kkkさんのソース
> img =(int**)malloc((*width) * (*height) * 3);

元のC++ソース
>(*img)=new int[(*width)*(*height)*3];

malloc(sizeof(int) * (*width) * (*height) * 3)では?



No.15382

Re:mallocとポインタについて
投稿者---kkk(2004/07/09 18:38:06)


ありがとうございます.
しかし,その場合もいろいろと試したのですが
だめでした.
P6
551,477
255
Segmentation fault

というエラーがでてしまって


No.15381

Re:mallocとポインタについて
投稿者---kkk(2004/07/09 18:35:34)


int
load_ppm_file(int **img, char *filename, int *width, int *height)
{
FILE *fp;
char magic[BUFSIZ];
int maxlevel, x;

fp = fopen(filename, "r");
if (fp == NULL)
return -1;

fscanf(fp, "%s %d %d %d", magic,width,height,&maxlevel);

printf("%s?n",magic);
printf("%d,%d?n",*width,*height);
printf("%d?n",maxlevel);

if (strncmp(magic, "P6", 2))
{
fprintf(stderr, "Error: %s is not raw ppm format!?n", filename);
exit(1);
}

(*img) =(int**)malloc((*width) * (*height) * 3);

if(*img==NULL){
printf("ERROR");
exit(1);
}

for (x = 0; x < (*width) * (*height) * 3; x++){
(*img)[x] =( 0x00ff & fgetc(fp));
}

fclose(fp);
free(*img);
return 0;
}
すみません.ソースをのせさせていただきます.
どうしてもエラーがでてしまって自分ではどうしようもないので.


No.15383

Re:mallocとポインタについて
投稿者---ぽこ(2004/07/09 18:56:33)


この関数を呼び出す時の第一引数に当てる変数は
どのように定義されてますか?

int main()
{
 int **img;//この変数定義で

 load_ppm_file(img,(後は省略));//第一引数に持ってくるとNG

}

上記のようなことやってませんか?




No.15384

Re:mallocとポインタについて
投稿者---kkk(2004/07/09 19:08:44)


><pre>
この関数を呼び出す時の第一引数に当てる変数は
どのように定義されてますか?

int main()
{
int **img;//この変数定義で

load_ppm_file(img,(後は省略));//第一引数に持ってくるとNG

}

上記のようなことやってませんか?
int *imin, *imout;
load_ppm_file(&imin, imin_name, &width, &height);

のようにして関数を読み出しているのでいいとおもうのですが

いま
(img) =(int**)malloc(sizeof(int*)*(*width) * (*height) * 3);
if(img==NULL){
printf("ERROR");
exit(1);
}
for (x = 0; x < (*width) * (*height) * 3; x++){
(*img)[x] =( 0x00ff & fgetc(fp));
}
としたら,forループまではとおったのですが
forルーポの値を入れるところでSegmentation faultとなってしまいました


No.15385

Re:mallocとポインタについて
投稿者---あかま(2004/07/09 19:44:17)


一次元配列なの?多分みんな二次元だと思ってるような。
いや、それだとポインタのポインタのポインタが必要か。

とりあえず、一次元ならこうかな。

*img =(int*)malloc(sizeof(int)*(*width) * (*height) * 3);
if(*img==NULL){
    printf("ERROR");
    exit(1);
} 
for (x = 0; x < (*width) * (*height) * 3; x++){
    (*img)[x] =( 0x00ff & fgetc(fp)); 
}

heightとwidthをポインタで渡す必要はないよね。
あと関数の最後でfree(*img);してしまってるけどいいのでしょうか?
関数内限定ならimgを引数で渡す必要さえないのですが。

個人的には、確保した配列の先頭アドレスを返すようにすれば、
余計なポインタのポインタとか考えなくてすむので楽だと思います。

あとお約束の一言(重要)
ソースを添付するときは「HTML変換ツール」を使ってください。




No.15386

Re:mallocとポインタについて
投稿者---ぽこ(2004/07/09 19:55:36)


>(img) =(int**)malloc(sizeof(int*)*(*width) * (*height) * 3);
> if(img==NULL){
> printf("ERROR");
> exit(1);
> }
> for (x = 0; x < (*width) * (*height) * 3; x++){
> (*img)[x] =( 0x00ff & fgetc(fp));
> }
>としたら,forループまではとおったのですが
>forルーポの値を入れるところでSegmentation faultとなってしまいました

このソースコードでは本当にkkkさんが仰る所で
セグメントフォールトが出てるか分かりません。
for文の前に次のコードを挿入してください。
printf("img = %p, *img=%p\n",img, *img);
これが出力されますか?
どんな出力になりますか?

#(*img) = (int*)malloc(略);じゃないですか?



No.15387

Re:mallocとポインタについて
投稿者---NykR(2004/07/09 19:59:52)


>(img) =(int**)malloc(sizeof(int*)*(*width) * (*height) * 3);

では、imgはポインタの配列の先頭要素へのポインタになりますが、この要素の値は不定です。

> (*img)[x] =( 0x00ff & fgetc(fp));

では、配列の先頭要素(*img)を参照していますが、不定の値は参照してはいけません。
少なくとも領域確保は、

*img = (int*)malloc(sizeof(int) * (*width) * (*height) * 3);

の様にすべきでしょう。

というか中で解放するなら
int load_ppm_file(int *img, const char *filename, int *width, int *height)
{
    // ...snip

    img =(int*)malloc(sizeof(int) * (*width) * (*height) * 3);

    if(img==NULL){
        printf("ERROR");
        exit(1);
    }

    for (x = 0; x < (*width) * (*height) * 3; x++){
        img[x] =( 0x00ff & fgetc(fp));
    }

    fclose(fp);
    free(img);
    return 0;
}

でいいと思うんですが。


No.15388

Re:mallocとポインタについて
投稿者---kkk(2004/07/09 20:33:06)


みなさんありがとうございます.
関数でppmファイルを取り込むのをやめて
mainでながながと書くようにしたら
ポインタのポインタもなくなり成功しました.
まだ,関数の中でのポインタのポインタでの領域の確保がよく
わかっていませんが,今回は成功したのでこれでいきたいと思っています.
ありがとうございました.


No.15377

Re:mallocとポインタについて
投稿者---ニタチ(2004/07/09 14:58:16)


>int load_pp_file(int **img, char*filename,int *width,int *height){
>FILE *fp;
>fp=fopen(filename,"r");
>
>*img=(int*)malloc((*width)*(*height)*3);
>
>for(x=0;x<(*width)*(*height)*3;x++)
> * img[x]=( 0x00ff & fgetc(fp) );

 こうじゃない?
 (*img)[x]=( 0x00ff & fgetc(fp) );