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

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

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

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

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

Q&A

解決済

4回答

6315閲覧

C言語 構造体連結リスト

koptooru

総合スコア7

C

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

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

0グッド

0クリップ

投稿2016/07/12 22:45

C言語で構造体の連結リストを作成しようとしているのですが
malloc corruptionとエラーメッセージが出ます

typedef struct _user {
char name[L_USERNAME];
int number;
struct _user *next;
}*user;

user make_user(char username[L_USERNAME], int socket) {
user newcp = malloc(sizeof(user));
以下要素の代入
}

新しいユーザーがログインするたびに関数make_userを呼び出しているのですが二回目でglibc detected memory corruption と出ます。デバッグを行ってみても
二回目のmallocでエラーが出ます

この書き方だと同じ場所のメモリを確保しようとするのでしょうか?

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

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

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

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

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

guest

回答4

0

typedef struct{/*中略*/}* userとなっているので、userはポインタです。

そのため、malloc(sizeof(user));ではポインタ分のサイズしか確保されていません。

typedef struct{/*中略*/} user, *puser;のようにして、構造体とポインタの差をはっきりさせましょう。

投稿2016/07/12 23:11

maisumakun

総合スコア145121

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

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

0

ベストアンサー

「要素の代入」にて、メモリ破壊が起きています。
原因は、maisumakunさんのコメントにある通りです。

少し細かく説明しますと…。

mallocにおいてサイズの指定を間違えています。
正しくは以下の通りです。

user newcp = malloc(sizeof(user))… ✕
user newcp = malloc(sizeof(struct _user))… ◯

sizeof(user)sizeof(struct _user *)。ポインタのサイズを取っています。
64bitの処理系なら 8 byteです。名前を入れるには到底足りないですよね。

要素の代入にて以下のような処理をしていると思いますが、

sprintf(newcp->name, username);

例えばusernameが"koptooru"だとしたら 8byte×8 で 64byte。
8byteしか確保してないので、確保したサイズを超えて書き込みますね。
これがメモリ破壊です。オーバーランとか言ったりもします。

メモリ破壊は厄介でして、壊した直後は落ちないことが多いです。
実際に破壊を検出するタイミングは、破損メモリにアクセスした時
だからです。一見、全く関係ない場所で落ちたりして焦ります。

今回、2回目のmake_userでエラーが起こるのは、make_userの
呼び出し時に破損メモリへのアクセスが発生するためと思われます。

~~~
上記、もっとも簡単な修正方法ですが、このやり方は良くないです。
maisumakunさんがおっしゃっているとおり、型定義(typedef)では
構造体の定義だけを行い、変数の宣言時にポインタ化するのが良いです。

投稿2016/07/13 00:01

tnd-.-b

総合スコア247

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

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

0

userがポインタ型なのでsizeof(user)では、アドレスサイズ分の確保になっていると思います。
maisumakunさんのように定義するか、sizeof(struct _user)とすれば正しく確保できると思います。

投稿2016/07/13 00:01

ttyp03

総合スコア16996

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

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

0

本当に malloc が原因でしょうか?
malloc した時点でエラーになるのか、それともそのあと要素を代入する時にエラーになるのかどちらでしょう?

メモリ破損の脆弱性/メモリ破壊の脆弱性(memory corruption vulnerability)

  • 動的にリスト確保したメモリを解放したにもかかわらず、再度解放してしまう
  • すでに解放済みのメモリ領域へアクセスしたり、データを書き込んだりでしまう
  • 演算ミスなどによって予期しないバッファ・サイズが割り当てられ、そこに書き込みや初期化処理を行ってしまう
  • 割り当てられた領域を超えて、アクセスしたり、データを書き込んだりしてしまう
  • ポインタ操作やアドレス演算のミスにより、予期しない場所に値を代入してしまう

投稿2016/07/12 23:01

Zuishin

総合スコア28656

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問