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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

4370閲覧

fgetcやfgetsでファイルの内容を表示しようとしたらsegmentation faultしてしまう。

sirami

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2020/05/20 09:05

編集2020/05/20 11:34

前提

HH-suiteという、タンパク質配列のデータベースを検索するプログラムをインストールしたのですが、
いざ検索を実行しようとするとsegmentation faultで停止してしまいます。

自分なりに原因を解明しようとしたところ、
どうやらfgetsやfgetcでデータベースのファイルの内容を読み取ろうとするとsegmentation faultしているみたいなのです。

ただ、自分はプログラミング初心者で、そのsegmentation faultが何を原因に起こっているかが理解できません。
fgetsやfgetcでsegmentation faultが起こる要因として何が考えられるでしょうか。

あと、重要な点として
サイズが小さいデータベース(全体で50GB)だとsegmentation faultが起こらず正常に作動するのです。
80GBぐらいのサイズが大きいデータベースに検索をかけようとするとsegmentation faultが起こります。
なので、巨大なファイルに対してfgetcをしたことが要因でsegmentation faultになっていると思うのですが……。

発生している問題・エラーメッセージ

- 16:46:58.159 INFO: Search results will be written to seq.fasta - 16:47:03.370 INFO: Searching 15161831 column state sequences. - 16:47:03.430 INFO: seq.fasta is in A2M, A3M or FASTA format - 16:47:03.431 INFO: Iteration 1 - 16:47:03.593 INFO: Prefiltering database - 16:49:45.411 INFO: HMMs passed 1st prefilter (gapless profile-profile alignment) : 314026 - 16:49:48.220 INFO: HMMs passed 2nd prefilter (gapped profile-profile alignment) : 2066 - 16:49:48.221 INFO: HMMs passed 2nd prefilter and not found in previous iterations : 2066 - 16:49:48.221 INFO: Scoring 2066 HMMs using HMM-HMM Viterbi alignment - 16:49:48.284 INFO: Alternative alignment: 0 Segmentation fault (core dumped)

該当のソースコード

プログラムが膨大すぎて貼ることができませんが、segmentation faultを起こすfgetsはここにあります。

C++

1// Emulates the ifstream::getline method; similar to fgets(str,maxlen,FILE*), 2// but removes the newline at the end and returns NULL if at end of file or read error 3inline char* fgetline(char str[], const int maxlen, FILE* file) { 4 if (!fgets(str, maxlen, file)) 5 return NULL; 6 if (chomp(str) + 1 >= maxlen) // if line is cut after maxlen characters... 7 while (fgetc(file) != '\n') 8 ; // ... read in rest of line 9 10 return (str); 11}

関数を呼び出している側はこうなってます。

C++

1char line[LINELEN]; 2if (!fgetline(line, LINELEN, dbf)) { 3   //TODO: throw error 4 HH_LOG(ERROR) << "In " << __FILE__ << ":" << __LINE__ << ": " << __func__ << ":" << std::endl; 5 HH_LOG(ERROR) << "\tThis should not happen!" << std::endl; 6}

ここでsegmentation faultする前に、 fgetc(dbf)と書いてみたところ、その段階でsegmentation faultしたのでdbf(FILE型)が問題になってます。
問題のdbfがどうやって得られたかは、あまりにもソースコードが膨大すぎてさっぱりわかりません。データベースから得られたのは明らかですが……。

試したこと

元々のプログラムは作成者のgitからcloneしたあと、自分でコンパイルしたものだったのですが、
condaというパッケージ管理ソフトから、コンパイル済みのものがインストールできたので、そちらも試しましたが同じく駄目でした。
データベース側のファイルは、ネットからダウンロードしたものをそのまま使っているので破損したりはしていないはずです。

補足情報(FW/ツールのバージョンなど)

windows10から、WSLでUbuntu 18.04を使っています。
プログラムはこちらからダウンロードしました。
https://github.com/soedinglab/hh-suite

追加情報

gdbというものを実行したうえでプログラムを走らせたところ、

Thread 1 "hhblits" received signal SIGSEGV, Segmentation fault. __strnlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:62 62 ../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory. (gdb) where #0 __strnlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:62 #1 0x00007ffffeac9fa1 in __old_fmemopen (buf=0xfdec293c1, len=6001, mode=0x80c229c "r") at oldfmemopen.c:245 #2 0x000000000807c5ce in HHDatabaseEntry::getTemplateHMM(Parameters&, char, float, int&, float*, float const (*) [20], float const (*) [20], HMM*) () #3 0x000000000808ede3 in ViterbiRunner::alignment(Parameters&, HMMSimd*, std::vector<HHEntry*, std::allocator<HHEntry*> >, float, float*, float const (*) [20], float const (*) [20], float const (*) [20], int, float const (*) [4][11], float const (*) [11][4][11], float const (*) [11][8]) [clone ._omp_fn.0] () #4 0x00007fffff63ce92 in GOMP_parallel ( fn=0x808eb80 <ViterbiRunner::alignment(Parameters&, HMMSimd*, std::vector<HHEntry*, std::allocator<HHEntry*> >, float, float*, float const (*) [20], float const (*) [20], float const (*) [20], int, float const (*) [4][11], float const (*) [11][4][11], float const (*) [11][8]) [clone ._omp_fn.0]>, data=0x7ffffff5bb80, num_threads=2, flags=0) at /home/nwani/m3/conda-bld/compilers_linux-64_1560109574129/work/.build/x86_64-conda_cos6-linux-gnu/src/gcc/libgomp/parallel.c:171 #5 0x000000000808fc5e in ViterbiRunner::alignment(Parameters&, HMMSimd*, std::vector<HHEntry*, std::allocator<HHEntry*> >, float, float*, float const (*) [20], float const (*) [20], float const (*) [20], int, float const (*) [4][11], float const (*) [11][4][11], float const (*) [11][8]) () #6 0x00000000080205fc in HHblits::run(_IO_FILE*, char*) () #7 0x0000000008012160 in main ()

と出ました。核心をついているような気もしますが、解読が出来ません・・・。
もしかしてstrlen-avx2.Sとやらを用意しておけばそれでオッケーってことなんですかね?
グーグルで調べてもあまり何のファイルなのかわかりませんが

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

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

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

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

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

SHOMI

2020/05/20 09:41

>データベース側のファイルは、ネットからダウンロードしたものをそのまま使っているので破損したりはしていないはずです。 再現手順を書かないとあなたにしか確認できませんよ。 それともし既存のIssuesと被っていないのであれば、Issuesに書いたほうがよいのでは? https://github.com/soedinglab/hh-suite/issues
cateye

2020/05/20 09:57 編集

ちゃんとCompilationやUser Guide読みましたか? ーーーー git clone https://github.com/soedinglab/hh-suite.git mkdir -p hh-suite/build && cd hh-suite/build cmake -DCMAKE_INSTALL_PREFIX=. .. make -j 4 && make install export PATH="$(pwd)/bin:$(pwd)/scripts:$PATH" ↑↑↑↑↑↑↑↑↑↑↑↑ この通りやっていますか?・・・てか、分かってやってますか? cmakeのパラメタが気になるんだけど・・・-G "Unix Makefiles"とかなくて良いのか?  -j 4は自分のPCに合わせて・・・
sirami

2020/05/20 10:07

cateyeさん、そうです、まさにその通りやりました! 他にもhttps://qiita.com/Ag_smith/items/401291c22fca19d61af9には別のインストール方法が紹介されていて、そっちでも試しましたが駄目でした。 なのでプログラムが原因じゃなくて、私のPCの設定(スタックサイズ?とか)が原因な気がしてますが、どう思いますか? fgetsで調べると、バッファオーバーランがどうとかって書いてあるので、まさにそれなんじゃないかと
cateye

2020/05/20 10:10

WSL上のUbuntuって何か制約(メモリとか)無いですか?
SHOMI

2020/05/20 10:22 編集

>問題のdbfがどうやって得られたかは、あまりにもソースコードが膨大すぎてさっぱりわかりません ソース内数回のgrepで出てきましたが… メモリ上から読んでいますね。 ffdatabase,ffdatabase->db_data, entryあたりがおかしな場所を指していたり?もしくはその領域にそもそも読み込めてないなかったり FILE* dbf = ffindex_fopen_by_entry(ffdatabase->db_data, entry); char* ffindex_get_data_by_offset(char* data, size_t offset) { return data + offset; } FILE* ffindex_fopen_by_entry(char *data, ffindex_entry_t* entry) { char *filedata = ffindex_get_data_by_offset(data, entry->offset); return fmemopen(filedata, entry->length, "r"); }
sirami

2020/05/20 10:35

cateyeさん、メモリの制約については調べてもわからなかったんですが、タスクマネージャーから見るとプログラム実行中に4GBくらい使ってたりするので制約に関してははあまり問題ないんじゃないかと思います。 WSLと関係あるか分かりませんがもしかしたらstacksizeがいけないんじゃないかと思っていました。ただroot権限でulimit -s unlimitedでstacksizeを無制限にした状態でプログラムを実行しても同じ現象が起こったので微妙に違う気がしてます。あまり意味のある情報を出せなくてすいません・・・ SHOMIさん、ありがとうございます。もういっそのこと、C++をちゃんと学んで、ソースコードから同じ流れを再現してみて、おかしいところがどこかちゃんと見たほうがいいんですかね。形式が同じでサイズが小さいデータだと成功しているというところから考えて、やっぱりバッファオーバーランみたく、サイズが大きいことで何かの枠組みからはみ出して変なメモリを指してしまうことでエラーが起きてる?みたいなのが濃厚な気がしてます。
SHOMI

2020/05/20 11:42

>もしかしてstrlen-avx2.Sとやらを用意しておけばそれでオッケーってことなんですかね? 違います __strnlen_avx2でSegmentation faultが発生したけれど、そのソースファイルが見つからないと言っているだけです
guest

回答1

0

あるあるなはなしですが、そういうのはエラーが出る場所がおかしいんではありません。
全く別なところのミスが、たまたまその場所でおかしくなっただけ、です。

fgetsやfgetcにばかり注目してる限り、問題は解決しません

投稿2020/05/20 09:13

y_waiwai

総合スコア87747

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

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

sirami

2020/05/20 09:39

回答ありがとうございます。ただ、もう少し意見が欲しいです。 fgetsでsegmentation falutが起こったのにはそれなりの理由があるのではないですか? 「全く別なところのミス」を突き止めるために、その理由として何が考えられるのかを知りたいのです。 それを「たまたま」と片付けてしまったら、また1から手掛かりを探すことになりますので……。
y_waiwai

2020/05/20 10:11

CとかC++はそういうもんなんです 実行時エラーは基本チェックしません。範囲外アクセスでアカンところが書き換わってもチェックされないのでそのまま処理が進み、別のところでその書き変わったことが原因で破綻して、初めてエラーとして出てきます とにかくポインタを使ってるところ、領域確保/開放関係、配列の範囲外などなど、チェックしてみてください。 VisualStudioやEclipseなどのデバッグできる環境を整え、変数やポインタの値をチェックしながらステップ実行させるなど。。 がんばってください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問