コンパイルは通るのですがエラーが出て実行できない。とりあえずわかる範囲でデバッグしてみました。
エラーの箇所は実行結果に示してあります。。どう直せばいいかがわかりません。
コード
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define N 256
#define FILENAME "address.csv"
struct address{
char number[N];
char name[N]; // 名前
char address[N]; // 住所
char tel[N]; // 電話
struct address *before; // ソートに必要である ,前のリスト
struct address *next; // 次のリスト
};
void list_add(struct address **ap,char *number, char *name, char *address, char *tel)
{
struct address *p;
if ((p = malloc(sizeof(struct address))) != 0) {
strcpy(p->number, number);
strcpy(p->name, name);
strcpy(p->address, address);
strcpy(p->tel, tel);
p->next = *ap; // *apの先頭アドレスをポインタpのp->nextに代入する。
// p->nextはstruct address *pの中で次のリストをしめしている。
// ポインタpの次のリストに追加したいstruct address **apの先頭アドレスを代入する。
// *apはheadである。
printf("p:%p\tnext3: %p\tbefore: %p \t*ap: %p\n", p, p->next, p->before,*ap);
if (p->next != 0) // 代入された*apの先頭アドレスが0でないならば
printf("p:%p\tnext3: %p\tbefore: %p\n", p, p->next, p->before);
p->next->before = p;
printf("p:%p\tnext3: %p\tbefore: %p\n", p, p->next, p->before);
p->before = 0;
// *apをheadにするために次のリストのp->beforeを0にしている。
printf("p:%p\tnext3: %p\tbefore: %p\n", p, p->next, p->before);
*ap = p; // *apをheadにしている。
printf("p:%p\tnext3: %p\tbefore: %p \t*ap: %p\n", p, p->next, p->before,*ap);
}
}
void release(struct address **ap)
{
if (*ap != 0) {
release(&((*ap)->next));
free(*ap);
*ap = 0;
}
}
void chop(char *p) {
for (; *p; p++)
;
p--;
while (*p == '\r' || *p == '\n')
*(p--) = 0;
}
int main(void)
{
struct address *ap;
FILE* fp;
static char buff[N],number[N], name[N], address[N], tel[N];
char *token=",";
ap = 0;
if ((fp = fopen(FILENAME,"r")) != 0) {
while(fgets(buff, N, fp) != 0){
chop(buff);
strcpy(number, strtok(buff, token));
strcpy(name, strtok(NULL, token));
strcpy(address, strtok(NULL, token));
strcpy(tel, strtok(NULL, token));
list_add(&ap,number,name, address, tel);
}
fclose(fp);
}
release(&ap);
return 0;
}
/* 実行結果
とりあえずわかる範囲でデバッグしてみました。
エラーの箇所は以下で起きています。どう直せばいいかがわかりません。
main () at list_add.c:75
75 strcpy(number, strtok(buff, token));
(gdb)
76 strcpy(name, strtok(NULL, token));
(gdb)
77 strcpy(address, strtok(NULL, token));
(gdb)
78 strcpy(tel, strtok(NULL, token));
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x77915633 in strcat () from C:\WINDOWS\SysWOW64\msvcrt.dll
(gdb)
*/
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
void chop(char *p) {
for (; *p; p++)
;
p--;
while (*p == '\r' || *p == '\n')
*(p--) = 0;
}
これだと"\0"を渡すと領域外にアクセスする
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
原因をどなたかがコメントされるかも知れませんが・・・
自分は問題発生時の取り組み方をコメントしてみようと思います。(すみませんがコードはよく見てません)
SIGSEGVですので、「アクセスしてはいけないアドレスをさわってしまった」ということですね。
- 不当アドレスの入ったポインターpに対して*pをアクセスした
- 正しいアドレスを指定せねばならない関数へ正しくないアドレスを渡した
例えばNULLを指定するとNGな引数にNULLを渡したとか・・・ - 文字列の終端文字(NUL文字)がなくてstrcpyで触ってはいけない領域に触れてしまった
などなど・・・
様々な原因が考えられます。特定するときのコツは「自分が正しいことをしている確信を持つ」ことです。確信を持つには関数の仕様やCの言語仕様の曖昧な点を(リファレンスや教科書を見直して)確認することも大事と思います。
そういう観点でより具体的なデバッグ結果を提示するとよりよい質問になると思います。(残念ながらご質問の内容ではデバッグしたとは言い難い・・・ですw;)異常終了した行が特定できているならその関数を呼び出す際にどのような引数を指定したかも当然しらべるべきですから。
どう直せばいいかがわかりません。
直し方より原因を掴むのが先ですよ!
追記:(大した話ではないですが)
異常終了する付近を調べる際、仕様を勘違いしていたり動作自体を勘違いしていたりといったことはよくあるので、少なくとも後者はデバッグプリントしておくと気づける場合もあります。
strcpy(name, strtok(NULL, x));
// ここでstrcpyの第二引数にNULLを渡すと致命的
// ならばデバッグするときは・・・
char* tmp1 = strtok(NULL, x));
printf("tmp1 = %p\n", tmp1);
strcpy(name, tmp1);
// などとすれば、より状況がつかみやすくなる・・・
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/11/27 20:34
あるプログラムを探して実行したときは実行できたのに、
今そのプログラムを実行してもエラーがでてしまいます。
そのプログラムからlist_addだけを実行するために抜粋してつくっています。
2017/11/27 20:50 編集
void chop(char *p) {
int len = strlen(p);
while (len > 0 && (p[len-1] == '\r' || p[len-1] == '\n')) *--p = '\0';
}
上記ではlen>0で「文字列先頭より前の領域を決してアクセスしない」という考え方にしてます。論理ができたらその後でポインターアクセスの最適化をすればよいのではないでしょうか。p[len-1]みたいなところの最適化です。
2017/11/27 20:57
修正ありがとうございます。
2017/11/27 21:13 編集