dポイントプレゼントキャンペーン実施中!

構造体へのポインタを動的確保しようとmalloc関数を使用すると
segmentation faultが起きます。

typedef struct cell{
char *word;
int count;
struct cell *next;
}node_t;

という構造体で

node_t *ptr=(node_t*)malloc(sizeof(node_t)*num);

という風に動的確保しようとするとsegmentation faultが起きました。

gdbを使って調べると

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

というメッセージが返ってきます。

これはライブラリとのリンクが正しく行われていないということでしょうか?

しかし、ポインタの動的確保以外でmalloc関数を使用すると
正常に動作するのでライブラリ自体が無いわけではないようです。

ptr[2]といった風にポインタを参照したいのですが上手くいきません。

よろしくお願いします。

A 回答 (8件)

まぁ、もろもろ指摘が既に入っていますが……。



nodePrepend()にブレークポイント張って、変数の「中身」を確認しながらステップ実行して下さい。
たぶん、forループが1回まわる前に気づくでしょう。
    • good
    • 1
この回答へのお礼

*listを初期化してnodePrepend内に条件分岐を加えたら
ヒープソートまでできるようになりました。
ありがとうございましたm(_ _)m

お礼日時:2014/11/11 16:37

よく見たら、その前に num をインクリメントしてますね。


その必要があるかどうかわかりませんが、そのために
p が NULL になってしまいますね。
    • good
    • 0

直接のエラーの原因は


for (i = 1, p = list; i <= num; i++, p = p->next) {
ptr[i] = *p;
}
ここでしょう。
配列をnum個しか確保していないのに、num番目を使ってはいけません。
C言語での配列は、0~num-1を使用します。

また、
free(p);
と解放していることも変ですね。
    • good
    • 0

>Program received signal SIGSEGV, Segmentation fault.


>0x00007ffff7b4ce36 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
>というのは、main関数に入る前に
>segmentation faultを起こしているように思えるのですが
>どうなのでしょうか。

自分の書いたコードに非はないと思い込みたい気持ちはわからなくないですが、nodePrependの使い方がおかしいです。
nodePrependを呼び出す前にやるべき事を忘れていませんか。
    • good
    • 0
この回答へのお礼

*listを初期化していませんでしたね…
ありがとうございました。

お礼日時:2014/11/11 16:34

うん, それはコケると思う. デバッガで調べてもらえばわかるはずだけど, nodePrepend がまともに動かないんじゃないかな.



そして問題は nodePrepend にはないという....
    • good
    • 0
この回答へのお礼

*listを初期化していなかったからでしょうか。
初期化をしたら問題なくヒープソートまでできました。
ありがとうございましたm(_ _)m

お礼日時:2014/11/11 16:34

>この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を起こしているように思えるのですが
どうなのでしょうか。

よろしければ引き続きお願い致します。

補足日時:2014/11/10 23:14
    • good
    • 0

>動的確保以前のプログラムは正しく動作するのですが……



そういう場合は「正しく動作しているように見えてるだけ」という事もあります。

うちの環境は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
%

何の問題もなく動きますけど。
    • good
    • 0

>node_t *ptr=(node_t*)malloc(sizeof(node_t)*num);


>という風に動的確保しようとするとsegmentation faultが起きました。

本当にそのmallocで起きてるsegmentation faultですか。
その後に書いてる何らかの処理で起きてるんじゃないですか?

この回答への補足

このmallocの後にfree(ptr)だけを書いてもsegmentation faultが起きます。
また、このmallocとfreeをコメントアウトすると
動的確保以前のプログラムは正しく動作するのですが……

補足日時:2014/11/10 20:34
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!