🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Q&A

解決済

4回答

2081閲覧

メモリ解放エラー文のないコアダンプ

ZhenZeZhang

総合スコア33

C

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

0グッド

0クリップ

投稿2019/11/04 09:22

プログラムの謎のコアダンプが出ることによりいろいろ検査したところ、謎が解決できず質問させていただきます。

コード構成: pref.cの中はmainから受けっとった構造体のデータをポインタに代入することと それをポインタ使って表示する機能を持つ。

pref2mnain.c ではデータを保持している。また、自作構造体のポインタ変数を所持して、最後に(ここからコアダンプが出たところで)構造体ポインタ変数(p)のメモリ解放をする。(free)

Code構成 分割コンパイルして実行し、それぞれCodeを下に掲載 (pref.c pref2main.c pref.h )

また gcc のコマンドは $ gcc -c -Wall -O3 pref.c pref2main.c && gcc pref.o pref2main.o && ./a > out.txt && diff -Bw out.txt pexp.txt
です。(pexp.txt は以下となります)

Tokyo 2187.65 12988797
Osaka 1898.01 8840372
Hyogo 8395.89 5599359

解決したいこと:pref2mian.c(このソース内部だけを編集してそのCode)の中でメモリの解放を行ってかつコアダンプにならないようにしたい。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include "pref.h" pref_t *pref_new(char *na, double ar, int pop){ pref_t *a=NULL; fprintf(stderr, "211 "); a= (pref_t *)malloc(sizeof(pref_t)* (strlen(na) + 1)); strcpy(a->name, na); a->area= ar; a->population= pop; return a; } void pref_print(pref_t* p){ printf("%s %0.2lf %d\r\n", p->name, p->area, p->population); fprintf(stderr, "223 "); }
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "pref.h" #define NAMELEN 15 int main(void){ pref_t *g[3], p[3]= { {"Tokyo", 2187.65, 12988797}, {"Osaka", 1898.01, 8840372}, {"Hyogo", 8395.89, 5599359} }; fprintf(stderr, "asd \n0 "); for(int i=0; i< 3; i++) { g[i] = &p[i]; pref_new(g[i]->name, g[i]->area, g[i]->population); } fprintf(stderr, "\n1 "); for(int i=0; i< 3 ; i++) { pref_print(g[i]); // free(g[i]); } for(int i=0; i< 3 ; i++) { free(g[i]); g[i]=NULL; } fprintf(stderr, "\n2 "); return 0; }
#define NAMELEN 15 typedef struct { char name[NAMELEN+1]; /* 県名 */ double area; /* 面積 (km2)*/ int population; /* 人口 (人) */ } pref_t; pref_t *pref_new(char *name, double area, int population); void pref_print(pref_t* p);

もし解決できる方がいっらしゃれば、ここでの原理を説明したサイトリンクでもいいですので理由とともに教えていただければ大変感謝しております。

ありがとうございます。

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

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

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

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

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

cateye

2019/11/04 09:30

pref_new(g[i]->name, g[i]->area, g[i]->population); の復帰値は誰が受け取るのでしょう?
ZhenZeZhang

2019/11/04 09:45

メッセージありがとうございます。ほかの方からの回答を読んだところ、そちらのほうでおそらく問題があるようですので、自分はmainのほうで調整してみます。
guest

回答4

0

freeできるのはmallocしたものだけです。
g[i] = &p[i];としているので、g[i]はローカル自動変数のアドレスであり、freeの対象ではないです。

mallocした結果のアドレスは使ってませんね。
あと、a= (pref_t *)malloc(sizeof(pref_t)* (strlen(na) + 1));のサイズもおかしいです。なぜ掛け算する??

投稿2019/11/04 09:53

otn

総合スコア85882

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

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

ZhenZeZhang

2019/11/04 10:12

やはりアドレスが使われていないようですね。メッセージありがとうございます。自分はfreeを除いたコードを実行して結果が正しく出たのですが、それはそうしてですか?
otn

2019/11/04 10:15

単に、プログラム中で定義した pref_t p[3] の中身を表示しただけなので、正常に表示できます。
ZhenZeZhang

2019/11/04 10:30

ですが、自分はg[i]を使って表示しているので、まだ少し疑惑しているところがあります。もう少し見てみます。
otn

2019/11/04 10:45

g[i] = &p[i];なので、g[i]とp[i]は同じです。
ZhenZeZhang

2019/11/04 10:57

そうでしたですね。ポインタの初学者でいろいろ学んでいく中見失ってしまいました。
ZhenZeZhang

2019/11/04 10:57

ありがとうございます。
guest

0

pref_new()の中で確保されたメモリを指すポインタ(pref_new()がreturnするポインタ)を、main()で受け取っていません。確保したけどポインタを誰も管理していないので、メモリリークしてしまうのだと思います。

また、free()しようとしているポインタはpref_new()の中で確保されたメモリを指すポインタではなく、main()の最初の行でスタック上に確保したメモリへのポインタになってしまっていて、コアダンプしてしまうのでしょう。

まずは、pref_new()でreturnされるポインタを管理するように修正してみてください。

投稿2019/11/04 09:36

segavvy

総合スコア1038

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

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

ZhenZeZhang

2019/11/04 10:08

はい。わかりました。修正してみます。ありがとうございます。
guest

0

明らかにもう、おかしい部分は、main関数中で

C

1 for(int i=0; i< 3; i++) { 2 g[i] = &p[i];

g[i]にポインターを入れているところを

C

1 for(int i=0; i< 3 ; i++) { 2 free(g[i]); 3 g[i]=NULL; 4 }

と、freeで処理しているところです。ここで落ちるか、その後のコアダンプに影響しているのでは。
pref_new関数内でmallocで動的割り当てし、そのポインターを返り値として返していますが、使っていません。

投稿2019/11/04 09:34

編集2019/11/04 09:38
dodox86

総合スコア9254

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

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

ZhenZeZhang

2019/11/04 10:08

メッセージありがとうございます。使ってないことに気づきませんでした。ありがとうございます。
guest

0

自己解決

prefコード全体をかえました。ありがとうございます。

#include <stdlib.h> #include "pref.h" #define NAMELEN 15 int main(void) { pref_t *g[3]= { pref_new("Tokyo", 2187.65, 12988797), pref_new("Osaka", 1898.01, 8840372), pref_new("Hyogo", 8395.89, 5599359) }; for(int i=0; i< 3 ; i++) { pref_print(g[i]); free(g[i]); g[i]=NULL; } return 0; }

投稿2019/11/04 11:00

ZhenZeZhang

総合スコア33

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問