アプリ版:「スタンプのみでお礼する」機能のリリースについて

C言語について教えてください。

大学の課題でCを書いています。
freeの仕方について教えてください。

構造体
struct word {
struct word *next;
char *st;
int *line_no;
int line_cnt;
};

を用意し、char* stにstrdupにて文字列を格納します。
そして、簡単なリストを作り、表示をさせfreeをするプログラムです。

freeをする際にfreeしてはいけないメモリをfreeしているようです。
しかし、正しい場所をfreeしていると思うので、なぜエラーなのか分かりません。
理由と解決方法を御教授願えませんでんしょうか。
よろしくお願いします。


/************以下ソース****************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct word {
struct word *next;
char *st;
int *line_no;
int line_cnt;
};

struct word *head;

void Add_List(char *buf,int no){

struct word* node = malloc(sizeof(struct word*));
struct word* crnt;

/*nodeの準備*/
node->next = NULL;
node->st = strdup(buf);
node->line_no = malloc(sizeof(int*));
node->line_no[0] = 1;
node->line_cnt= 1;

if(head == NULL) {
head = node;
} else {
crnt = head;

while( crnt->next != NULL) {
crnt = crnt->next;
}

crnt->next = node;
}
}

void printlist(){

struct word *crnt = head;

while( crnt != NULL ) {
printf("%s\n",crnt->st);
crnt = crnt->next;
}

}

int main(){

head = NULL;

char buf1[] = {'A','B','C','D','E','\0'};
char buf2[] = {'F','G','H','I','J','\0'};
char buf3[] = {'K','L','M','N','O','\0'};


Add_List(buf1,1);
Add_List(buf2,1);
Add_List(buf3,1);

printlist();

/*この部分がうまくいかない*/
free(head->st);
/*********************/

}


(以下実行結果です。OS:CentOS)

[yuichiro-ito@localhost test]$ ./a.out
ABCDE
FGHIJ
KLMNO
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0000000001a01030 ***
======= Backtrace: =========
/lib64/libc.so.6[0x365a4760e6]
./a.out[0x40072f]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x365a41ecdd]
./a.out[0x4004d9] 
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:02 390975 /home/yuichiro-ito/test/a.out
00600000-00601000 rw-p 00000000 08:02 390975 /home/yuichiro-ito/test/a.out
01a01000-01a22000 rw-p 00000000 00:00 0 [heap]
3659c00000-3659c20000 r-xp 00000000 08:02 785966 /lib64/ld-2.12.so
3659e1f000-3659e20000 r--p 0001f000 08:02 785966 /lib64/ld-2.12.so
3659e20000-3659e21000 rw-p 00020000 08:02 785966 /lib64/ld-2.12.so
3659e21000-3659e22000 rw-p 00000000 00:00 0
365a400000-365a58a000 r-xp 00000000 08:02 785967 /lib64/libc-2.12.so
365a58a000-365a789000 ---p 0018a000 08:02 785967 /lib64/libc-2.12.so
365a789000-365a78d000 r--p 00189000 08:02 785967 /lib64/libc-2.12.so
365a78d000-365a78e000 rw-p 0018d000 08:02 785967 /lib64/libc-2.12.so
365a78e000-365a793000 rw-p 00000000 00:00 0
3666c00000-3666c16000 r-xp 00000000 08:02 785985 /lib64/libgcc_s-4.4.7-20120601.so.1
3666c16000-3666e15000 ---p 00016000 08:02 785985 /lib64/libgcc_s-4.4.7-20120601.so.1
3666e15000-3666e16000 rw-p 00015000 08:02 785985 /lib64/libgcc_s-4.4.7-20120601.so.1
7fc7b9e92000-7fc7b9e95000 rw-p 00000000 00:00 0
7fc7b9ea0000-7fc7b9ea3000 rw-p 00000000 00:00 0
7fffbce3c000-7fffbce51000 rw-p 00000000 00:00 0 [stack]
7fffbce9d000-7fffbce9e000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

A 回答 (1件)

free()の使い方ではなくてmalloc()の使い方が間違ってます.



> struct word* node = malloc(sizeof(struct word*));

これだと sizeof(struct word*) バイト、つまりポインタのバイト数 (普通、4バイトとか8バイト)のメモリ しか
確保されていません。
そこに無理矢理構造体のデータを書き込んでしまっているのでメモリ管理が破綻してます。


構造体本体を確保する場合はこうします。

struct word* node = malloc(sizeof(struct word));


> node->line_no = malloc(sizeof(int*));

こちらも同様。 ポインタ line_no で示される位置に格納されるのは int* ではなくて int ですから

node->line_no = malloc(sizeof(int));

とします。

余談ですが、malloc()やstrdup()などで動的にメモリを確保した際には、必ずNULLかどうかチェックしてメモリ不足を捕まえておかないと後で苦労する事になります。
(本格的なプログラムを書き始めると、それこそどこが原因でエラーが起きてるのか判らなくなります)

今からCを習得されるのでしたら、C++から入った方が楽です。
malloc()しません.し、
( struct word* node = new struct word; とします)
もし間違って struct word* node = new struct word*;
と書いてしまった場合ばコンパイラがエラー吐いて教えてくれますから.
    • good
    • 1

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