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

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

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

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

Q&A

解決済

4回答

3322閲覧

seekgやclearでsegfaultになる

mentos109

総合スコア28

C++

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

1グッド

1クリップ

投稿2019/08/31 06:25

編集2019/08/31 11:09

C++にて、他プログラムが書き込み中のプログラムを読み取り専用で開き、whileループで繰り返しデータを読み取っているのですが、
たまにseekgでsegmentation faultが発生しプログラムが落ちてしまいます。
ネットで調べても、readやopenでのsegfaultの問題などは見つかりますが、seekgでのsegfaultは見つかりません。
原因は何でしょうか?また、どうすれば解決できますか?やはり他プログラムで同時に同ファイルへの書き込みを行っているのが問題なのでしょうか?
ちなみに直前でclear()を実行するようにしてもsegfaultになり、その場合はclear()実行時にsegfaultが発生します。
seekg(0, std::ios_base::beg)でファイルの先頭に移動しようとしても同じようにsegfaultが起きてしまいます。
よろしくお願いします。

C++

1std::ifstream ifs("./a", std::ios::in|std::ios::binary); 2while(1) { 3 int64_t offset = ..; 4 size_t size = ..; 5 char buf[size]; 6 //ifs.clear(); //←これを追記してもここで落ちる(ifs.seekg(0, std::ios_base::beg)でも落ちる) 7 ifs.seekg(offset, std::ios_base::beg); //←ここでたまに落ちる 8 if (ifs.read(buf, size)) { 9 .. 10 } else { 11 .. 12 } 13}
yumetodo👍を押しています

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

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

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

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

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

majiponi

2019/08/31 14:22

offsetやsizeを計算している部分など、..で書いている部分を開示してもらえますか? 関数で落ちているのではなく、その直前の領域確保で失敗していたりするかもしれないので。あと環境も。
mentos109

2019/08/31 14:40

offset、sizeの部分なのですが、ファイルへの書き込みを行っている別のプログラムAからプロセス間通信でオフセット、サイズ、ファイルパスをテキストデータで受け取っています。それを別スレッドが受信、キューにプッシュして、Aがsyncを実行したらすべてポップしてその情報を元にデータを読み取りに行っています。 環境はCentOS7 64bit、メモリ16GBのIntelCPUです。
majiponi

2019/08/31 15:12

その情報が間違っている可能性は? 例えばsizeで0とか-1とかが得られていると簡単に暴走しそうですが。
mentos109

2019/08/31 15:15

一応ログに吐いて確認してますが、そういったことにはなってません。また、seekgだけではなくclearを呼び出したり、ファイルの先頭にシークしようとしてもsegfaultになるので、そういったことが原因ではないと思われます。
mentos109

2019/09/07 14:42

解決いたしました。majiponiさんの仰るとおり直前での領域確保に失敗していました。軽い考えで否定してしまい大変失礼しました。
guest

回答4

0

こんにちは。

回答依頼を頂いたので、来てみました。
内容的には、majiponiさんの推測に1票入れます。
メモリ破壊が起こっていて、それがifsを壊しているのではないか?という推測です。

不正メモリ・アクセスは運が良い時は例外が発生しますが、例外も起きずにしらっとメモリが壊れて不正動作する場合があります。

投稿2019/09/04 12:33

編集2019/09/04 12:52
Chironian

総合スコア23272

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

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

mentos109

2019/09/04 12:41

回答ありがとうございます、念の為お聞きしたいのですが、他プログラムがファイルを書き換えている時などにかち合って読み込み専用でファイルを読み込もうとしても、基本的には例外やsegfaultは起きない、という認識でいいのでしょうか?つまり、やろうとしている事自体はできるが、単純にコードに不備があってうまくいってないという認識でよろしいでしょうか。
Chironian

2019/09/04 12:52

ifsの設定によってはエラーを例外で通知してきますが、segfaultは起きないと認識しています。 segfaultはC++の仕様にありませんからC++言語仕様内の動作でないことは間違いないです。 異常動作の原因は分かりませんが、経験上その殆どは自分のコードが原因です。 今回の場合は、範囲外のメモリへ書き込みしてないことをプログラムでチェックし、発生したらログを出力して例外で停止する等の対処を入れて、原因を追求するべきかと思います。
mentos109

2019/09/04 13:12 編集

わかりました、その線でコードを読み直してみようと思います、ありがとうございます。
yumetodo

2019/09/05 15:28

見れば見るほど謎が深まっていく・・・
mentos109

2019/09/07 14:40 編集

ulimitコマンドにてスタックサイズを増やしたところsegfaultにならなくなりました。 どうやらスタックオーバーフロー?しているようです。 確認したところ、segfaultになったタイミングでsizeの値を確認してみると、デフォルトのスタックサイズだった8192KBをオーバーしていました。 どうやら直前のchar buf[size]でオーバーフローしており、gdbでのバックトレースでは次の行で止まったことになっていました。そして色々とコードを追記して試したのですが、char buf[size]の次の行は運悪くすべてifstream関係のコードを追記して実験していたため、ifstream関係の不具合だと思いこんでしまったようです。
guest

0

ifs がスタック上に置かれて壊れているのなら、次のように
static を付けて、静的領域に置いてみたらどうなりますか?

C++

1#include <fstream> 2 3int main() 4{ 5 static std::ifstream ifs; 6 ifs.open("./a", std::ios::in | std::ios::binary); 7 while (1) { 8 // ... 9 } 10 ifs.close(); 11}

でも、スタックの中身が壊されるのなら、他の変数も壊されて、
あるいは、リターンアドレスが壊されて、関数の呼び出し元に戻れなくて
segmentation fault になっているのかもしれないので解決しないかも。

投稿2019/09/05 16:08

kazuma-s

総合スコア8224

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

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

mentos109

2019/09/06 06:13

回答ありがとうございます、ifsをグローバル変数において試してみましたが、同じようにsegfaultになってしまいました・・・coreファイルを出力させてgdbのbtで確認しているのですが、coreファイルも追いきれてないということもあるんでしょうか
kazuma-s

2019/09/06 06:53

プログラム全部を見せるか、バグが再現する最小限のプログラムを見せるかしないと、適切なアドバイスは期待できないでしょう。
mentos109

2019/09/06 10:16

やはりそうですよね、ありがとうございます。
guest

0

対象ファイルを別プロセス側で消してるんじゃないかなーと予想
読み取り側で開いてる(こうとしている)ときに消すのは環境次第ですが変な事になりそうで怖いですね

投稿2019/08/31 15:23

asm

総合スコア15149

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

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

yumetodo

2019/09/02 00:34

ファイルハンドル持ってるのに消せるもんなんですか・・・知らんかった
guest

0

ベストアンサー

毎回ファイルハンドルを取り直すべきです。

cpp

1std::string_stream buf_stream; 2{ 3 std::ifstream ifs("./a"); 4 buf_stream << ifs.rdbuf(); 5} 6//buf streamをなんかやる

投稿2019/08/31 07:05

yumetodo

総合スコア5852

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

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

mentos109

2019/08/31 07:24

回答ありがとうございます。 質問に記載しておらず後出しとなって申し訳ないのですが、このプログラムはかなりの高頻度で読み込みを行います。そのためファイルのオープンははじめのみにしたのですが、ファイルのオープンクローズのコストはあまり考えなくていいのでしょうか?
mentos109

2019/08/31 11:20

また、毎回自動変数を使ってファイルをオープンするようにしましたが、今度はopen()の段階で同じようにまれにsegfaultを起こすようになってしまいました。
yumetodo

2019/08/31 13:06

セグフォルってのがわからないんですよね、streamのエラーフラグが立つ、ならわかるんですが。
yumetodo

2019/09/08 10:39

やっぱりメモリー破壊でしたか。なぜ私の解答がBAになったのか謎ですがまあお疲れさまでした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問