質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

7859閲覧

c言語 free(): invalid pointer Aborted (core dumped)

pocomi

総合スコア3

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2022/03/06 15:41

編集2022/03/06 16:08

現在c言語のコードを書いてるのですが、コンパイルしようとするときに、
free(): invalid pointer
Aborted (core dumped)
っていうエラーメッセージが出てきます。

valgrindで調べてみたところ、どうやらこの関数に原因があるみたいですが、
原因がなかなか発見できません。直すべき点や解決方法などありましたら教えてほしいです。

C

1HEAP SUMMARY: 2==5996== in use at exit: 26 bytes in 5 blocks 3==5996== total heap usage: 10 allocs, 8 frees, 357 bytes allocated 4==5996== 5==5996== 9 bytes in 4 blocks are definitely lost in loss record 1 of 2 6==5996== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) 7==5996== by 0x10B84D: my_substr (my_substr.c:26) 8==5996== by 0x10AEF8: ssplit (my_split.c:57) 9==5996== by 0x10AFEE: my_split (my_split.c:79) 10==5996== by 0x109255: main (main.c:93) 11==5996== 12==5996== LEAK SUMMARY: 13==5996== definitely lost: 9 bytes in 4 blocks 14==5996== indirectly lost: 0 bytes in 0 blocks 15==5996== possibly lost: 0 bytes in 0 blocks 16==5996== still reachable: 17 bytes in 1 blocks 17==5996== suppressed: 0 bytes in 0 blocks 18==5996== Reachable blocks (those to which a pointer was found) are not shown. 19==5996== To see them, rerun with: --leak-check=full --show-leak-kinds=all

C

1char *my_substr(char const *string, unsigned int start, size_t len) 2{ 3 char *res; 4 size_t size; 5 char *tmp; 6 char *dup_put; 7 char *tmp_dup; 8 9 if (string == NULL) 10 return (NULL); 11 size = my_strlen(string); 12 if (size < start) 13 { 14 dup_put = my_strdup(""); 15 return (dup_put); 16 } 17 tmp = res; 18 if (size < len) 19 { 20 len = size; 21 } 22 res = (char *)malloc(sizeof(char) * (len + 1)); 23 if (res == NULL) 24 return (NULL); 25 my_strlcpy(res, string + start, len + 1); 26 free(tmp); 27 return (res); 28} 29 30static char **ssplit(char **res, const char *str, size_t col, const char c) 31{ 32 size_t i; 33 size_t j; 34 size_t len; 35 char **tmp; 36 37 i = 0; 38 j = -1; 39 while (++j < col) 40 { 41 tmp = res; 42 while (str[i] == c) 43 i++; 44 len = my_strup(str + i, c); 45 res[j] = my_substr(str + i, 0, len); 46 if (res[j] == NULL) 47 return (my_clear(res, j)); 48 i += len; 49 } 50 res[j] = NULL; 51 free(tmp); 52 return (res); 53} 54 55char **my_split(char const *str, char c) 56{ 57 char **ss; 58 size_t count; 59 char **put_ssplit; 60 61 if (!str) 62 return (NULL); 63 count = my_word_count(str, c); 64 ss = (char **)malloc(sizeof(char *) * (count + 1)); 65 if (!ss) 66 return (NULL); 67 put_ssplit = ssplit(ss, str, count, c); 68 return (put_ssplit); 69} 70 71int main(int argc, char **argv) 72{ 73 char *map_read; 74 char **after_split; 75 int fd; 76 int lem_i; 77 fd = open(argv[1], O_RDONLY); 78 79 while(map_read != NULL) 80 { 81 map_read = get_line(fd); 82 after_split = my_split(map_read, ' '); 83 lem_i = 0; 84 while(after_split[lem_i] != NULL) 85 lem_i++; 86 printf("%s\n", after_split[lem_i]); 87 } 88 free(map_read); 89}```

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/03/06 17:29 編集

追加・修正したコードでしたら、ご質問を編集してください。コメントも編集できます。 また、インデントにタブとスペースが混在しているとガタガタになってしまいます。予めインデントをどちらかに統一されると華麗になると思います。
pocomi

2022/03/07 09:27

使い始めたばかりで、色々と分かってなくてアドバイスありがとうございます!
guest

回答4

0

ベストアンサー

malloc は獲得したメモリ領域へのアドレスを返しますが、そのアドレスを入れた変数をコピーした所で新たなメモリ領域がさらに獲得されるわけではありません。単に同じメモリ領域を指す変数が増えただけです。
また free に渡した(mallocによって獲得した)メモリ領域は、そこを指す変数が幾つ有ろうとも一回実行すれば解放されます。(そこを指す全ての変数が無意味になります。)
従いまして tmp=res; とした後に free(tmp); を実行したなら res の指すメモリ領域も解放されており、以降そのアドレスを用いることは破壊でしかありません。
そして、 free に malloc したメモリ領域のアドレス(と NULL )以外を渡した時にどうなるかは…ご存じの通り、でしょうか。
ダングリングポインタとは|dangling pointerの危険性と回避
MEM00-C. メモリの割り当てと解放は、同じ翻訳単位内の同一抽象レベルで行う

「1行をスペースで分割して個々の文字列への配列を得る」というのがメインのようですので、string 系関数を用いずに書いてみました。
split は line を書き換えてその中にある文字列数を返し、
split2 は line は弄らず、返すメモリ領域はポインタ配列の直後に文字列を並べています。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4size_t split(char *line, int sep) { 5 if(line == NULL) return 0; 6 7 size_t count = 0; 8 for(char *p=line, *q=line; *p!=0; p++) { 9 while(*p == sep) p++; //skip 10 if(*p == 0) break; 11 12 count ++; 13 while(*p!=sep && *p!=0) *q++ = *p++; //copy 14 if(*p == 0) { 15 *q = 0; 16 break; 17 } 18 19 *q++ = 0; 20 } 21 return count; 22} 23 24char **split2(char *line, int sep) { 25 if(line == NULL) return NULL; 26 27 size_t length = 0; 28 for(char *p=line; *p; p++) length++; 29 30 char *lbuf = malloc(length + 1); 31 if(lbuf == NULL) return NULL; 32 for(char *dst=lbuf, *src=line; (*dst++ = *src++); ); //copy 33 34 size_t count = split(lbuf, sep); 35 36 char *p = lbuf; 37 for(int i=0; i<count; i++) while(*p++); 38 int total = p - lbuf; 39 40 char **buf = malloc(sizeof(char*)*(count+1) + total); 41 if(buf == NULL) { 42 free(lbuf); 43 return NULL; 44 } 45 buf[count] = NULL; //EndOfData 46 47 char *dst = (char *)&buf[count+1]; 48 char *src = lbuf; 49 for(int i=0; i<count; i++) { 50 buf[i] = dst; 51 while((*dst++ = *src++)); //copy 52 } 53 54 free(lbuf); 55 56 return buf; 57} 58 59void test(char *header, char *line) { 60 printf("-- %s --\n",header); 61 char **pa = split2(line, ' '); 62 if(pa == NULL) { 63 printf("NULL\n"); 64 } else { 65 for(int i=0; pa[i]; i++) printf("%d: '%s'\n", i+1, pa[i]); 66 free(pa); 67 } 68} 69 70int main(int argc, char **argv) { 71 test("1", NULL); 72 test("2", ""); 73 test("3", " "); 74 test("4", "ABC"); 75 test("5", " ABC"); 76 test("6", "ABC "); 77 test("7", "ABC DEF"); 78 test("8", "ABC DEF GHI"); 79 test("9", " ABC DEF GHI "); 80 81 return 0; 82}

plain

1-- 1 -- 2NULL 3-- 2 -- 4-- 3 -- 5-- 4 -- 61: 'ABC' 7-- 5 -- 81: 'ABC' 9-- 6 -- 101: 'ABC' 11-- 7 -- 121: 'ABC' 132: 'DEF' 14-- 8 -- 151: 'ABC' 162: 'DEF' 173: 'GHI' 18-- 9 -- 191: 'ABC' 202: 'DEF' 213: 'GHI'

投稿2022/03/08 09:29

編集2022/03/08 09:47
jimbe

総合スコア12632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pocomi

2022/03/08 15:00

本当にコードまで書いてくださり本当にありがとうございました 勉強不足でまだ理解できてない部分があるので頑張ります。 参考にさせていただきます!ありがとうございました
guest

0

malloc直後に確保されたポインタ値をプリント
free直前に解放されるポインタ値をプリント

してみては? 必ず同じ値がふたつ一組で現れるはずだから。そうならなければソコが間違い。

投稿2022/03/07 06:54

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

google翻訳
free():無効なポインタが中止されました(core dumped)

エラーメッセージが出たら、それで投げてしまわずに、なにを言わんとしているのかってことを理解しましょう
free 関数でエラーが出るってことは、freeするべきでない、してはいけない引数を与えてしまった、と言うことですね

投稿2022/03/07 01:51

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

my_substr()関数で未初期化のresがtmpに代入されています。
このtmpでfreeしようとしているのがまずいです。

そもそも、malloc()で確保したメモリをmy_substr()関数がreturnしているので、
free()はmy_substr()関数の呼び出し側で行うべきです。

投稿2022/03/06 15:50

TaroToyotomi

総合スコア1430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pocomi

2022/03/06 15:59 編集

ご回答ありがとうございます。 実は呼び出し元の方でも一度tmpに代入してからfreeをしています。 関数載せてなくてすみません。 ```C static char **ssplit(char **res, const char *str, size_t col, const char c) { size_t i; size_t j; size_t len; char **tmp; i = 0; j = -1; while (++j < col) { tmp = res; //ここで一度tmpの方に代入してます。 while (str[i] == c) i++; len = my_strup(str + i, c); res[j] = my_substr(str + i, 0, len); if (res[j] == NULL) return (my_clear(res, j)); i += len; } res[j] = NULL; free(tmp); return (res); } char **my_split(char const *str, char c) { char **ss; size_t count; char **put_ssplit; if (!str) return (NULL); count = my_word_count(str, c); ss = (char **)malloc(sizeof(char *) * (count + 1)); if (!ss) return (NULL); put_ssplit = ssplit(ss, str, count, c); return (put_ssplit); }```
pocomi

2022/03/06 16:10

コードを追加しました。見えずらくてすみません。
TaroToyotomi

2022/03/06 16:11

my_substr()が未初期化のポインタをfree()しようとしているのは変わらないですのでそこは修正しないといけません。 ssplit()の中でmy_split()がmalloc()したssをfree()しているのに、その後の処理でss(ssplit()がreturnしたres)を使っているのもまずいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問