- ベストアンサー
構造体へのポインタの動的確保について
- ポインタを動的確保しようとするとsegmentation faultが起きます。
- malloc関数を使用すると正常に動作するが、ポインタを参照する際に上手くいかない。
- ライブラリとのリンクの問題ではないか疑われる。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
まぁ、もろもろ指摘が既に入っていますが……。 nodePrepend()にブレークポイント張って、変数の「中身」を確認しながらステップ実行して下さい。 たぶん、forループが1回まわる前に気づくでしょう。
その他の回答 (7)
- bull1472
- ベストアンサー率66% (2/3)
よく見たら、その前に num をインクリメントしてますね。 その必要があるかどうかわかりませんが、そのために p が NULL になってしまいますね。
- bull1472
- ベストアンサー率66% (2/3)
直接のエラーの原因は for (i = 1, p = list; i <= num; i++, p = p->next) { ptr[i] = *p; } ここでしょう。 配列をnum個しか確保していないのに、num番目を使ってはいけません。 C言語での配列は、0~num-1を使用します。 また、 free(p); と解放していることも変ですね。
- wormhole
- ベストアンサー率28% (1626/5665)
>Program received signal SIGSEGV, Segmentation fault. >0x00007ffff7b4ce36 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 >というのは、main関数に入る前に >segmentation faultを起こしているように思えるのですが >どうなのでしょうか。 自分の書いたコードに非はないと思い込みたい気持ちはわからなくないですが、nodePrependの使い方がおかしいです。 nodePrependを呼び出す前にやるべき事を忘れていませんか。
お礼
*listを初期化していませんでしたね… ありがとうございました。
- Tacosan
- ベストアンサー率23% (3656/15482)
うん, それはコケると思う. デバッガで調べてもらえばわかるはずだけど, nodePrepend がまともに動かないんじゃないかな. そして問題は nodePrepend にはないという....
お礼
*listを初期化していなかったからでしょうか。 初期化をしたら問題なくヒープソートまでできました。 ありがとうございましたm(_ _)m
- Wr5
- ベストアンサー率53% (2173/4061)
>このmallocの後にfree(ptr)だけを書いてもsegmentation faultが起きます。 それだけだと起きそうにないと思われるんですけどねぇ。 念のため、 sizeof(node_t) はいくつになります? num に入っている値はいくつです? ポインタ2つにint型1つですから、たいしたサイズにはならないハズですけど。 # 64Bit環境っぽい…けど、特にオプション指定しなかった場合にint型が何ビットになったかなぁ…。 取得したポインタに対して何らかの操作を行った…とか、 32Bitと64Bitが混在した…とかでしょうかねぇ……。 周辺のコードを掲示した方がいいかも知れませんね。 # malloc()直後にfree()でも死ぬ…というのが変ですが…。 # numが異常な値でメモリ確保できなかった場合はNULL返却でしょうし。
補足
返答ありがとうございます。以下、コードです。 ------------------------------------- #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct cell{ char *word; int count; struct cell *next; }node_t; int readword(FILE *fp,char *s); node_t *alloc_node_t(node_t *ndPtr,char *s); void nodePrepend(node_t **ndPtrPtr,char *s); void selection_sort(node_t *ndPtr,int n); void listprint(node_t *ndPtr); void heapsort(node_t *ndPtr[],int n); void downheap(node_t *ndPtr[],int leaf,int root); void swap(node_t *ndPtr[],int i,int j); int main(int argc,char *argv[]){ int i,num=0; FILE *fp; char buf[32]; node_t *list,*p; for(i=1;i<argc;i++){ if((fp=fopen(argv[i],"r"))==NULL){ fprintf(stderr,"cannot open %s\n",argv[i]); return 1; } while(readword(fp,buf)!=0){ //文字列の読み取り nodePrepend(&list,buf); //線形リストへの追加 } fclose(fp); } for(p=list;p!=NULL;p=p->next){ num++; //要素数のカウント } selection_sort(list,num); //単純選択法によるソート listprint(list); //線形リストを表示 printf("----------------------------------------\n"); num++; node_t *ptr=(node_t*)malloc(sizeof(node_t)*num); //ポインタの配列の動的確保 for(i=1,p=list;i<=num;i++,p=p->next){ ptr[i]=*p; } /* heapsort(ptr,num); for(i=1;i<num+1;i++){ printf("%s %d\n", ptr[i]->word , ptr[i]->count); } */ free(p); return 0; } int readword(FILE *fp,char *s){ int ch,k=0; while((ch=getc(fp))==' '|| ch=='\t' || ch=='\n'){}; if(ch==EOF) return 0; s[k]=ch; k++; while((ch=getc(fp))!=' ' && ch!='\t' && ch!='\n' && ch!=EOF){ s[k]=ch; k++; } s[k]='\0'; return 1; } node_t *alloc_node_t(node_t *ndPtr,char *s){ node_t *p; p=(node_t *)malloc(sizeof(node_t)); p->word=(char *)malloc(strlen(s)+1); strcpy(p->word,s); p->count=1; p->next=ndPtr; return p; } void nodePrepend(node_t **ndPtrPtr,char *s){ node_t *ndPtr; for(ndPtr=*ndPtrPtr;ndPtr!=NULL;ndPtr=ndPtr->next){ if(strcmp(ndPtr->word,s)==0){ ndPtr->count++; return; } } ndPtr=alloc_node_t(*ndPtrPtr,s); *ndPtrPtr=ndPtr; } void selection_sort(node_t *ndPtr,int n){ int i,j,min_count,temp_count; char *min,*temp_word; node_t *p,*q,*k; for(i=0;i<n;i++){ p=ndPtr; if(i!=0){ for(j=0;j<i;j++){p=p->next;}; } min=p->word; min_count=p->count; k=p; for(q=p->next;q!=NULL;q=q->next){ if(strcmp(min,q->word)>0){ min=q->word; min_count=q->count; k=q; } } temp_word=p->word; temp_count=p->count; p->word=min; p->count=min_count; k->word=temp_word; k->count=temp_count; } } void listprint(node_t *ndPtr){ int i; while(ndPtr!=NULL){ for(i=0;i<ndPtr->count;i++){ printf("%s\n",ndPtr->word); } ndPtr=ndPtr->next; } } ---------------------------------------- 与えられた課題が 「ファイルから文字列を読み取り、単純選択法により文字が小さい順にソートする。 その後、ヒープソートにより出現回数の少ない順にソートする」 というものです。 読み取った文字列を線形リストに保存し、単純選択法によるソートまではできたのですが ヒープソートをするためにポインタを配列に動的確保しようとしたところで segmentation faultが起きました。 動的確保ができなかったのでヒープソートをする部分は省略していますが これでもsegmentation faultが起きます。 sizeof(node_t)は12、numは11のようです。 配列を動的確保せずにヒープソートした方がいいのでしょうか… また Starting program: /home/programII/week05/a.out file1 file2 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7b4ce36 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 というのは、main関数に入る前に segmentation faultを起こしているように思えるのですが どうなのでしょうか。 よろしければ引き続きお願い致します。
- wormhole
- ベストアンサー率28% (1626/5665)
>動的確保以前のプログラムは正しく動作するのですが…… そういう場合は「正しく動作しているように見えてるだけ」という事もあります。 うちの環境はlinuxではなくFreeBSDですけど % cat node.c #include <stdio.h> #include <stdlib.h> typedef struct cell { char *word; int count; struct cell *next; } node_t; int main(int argc, char **argv) { int num = 10; node_t *ptr = malloc(sizeof(node_t) * num); printf("%p\n", ptr); free(ptr); return 0; } % cc -o node node.c % ./node 0x801006100 % 何の問題もなく動きますけど。
- wormhole
- ベストアンサー率28% (1626/5665)
>node_t *ptr=(node_t*)malloc(sizeof(node_t)*num); >という風に動的確保しようとするとsegmentation faultが起きました。 本当にそのmallocで起きてるsegmentation faultですか。 その後に書いてる何らかの処理で起きてるんじゃないですか?
補足
このmallocの後にfree(ptr)だけを書いてもsegmentation faultが起きます。 また、このmallocとfreeをコメントアウトすると 動的確保以前のプログラムは正しく動作するのですが……
お礼
*listを初期化してnodePrepend内に条件分岐を加えたら ヒープソートまでできるようになりました。 ありがとうございましたm(_ _)m