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

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

ただいまの
回答率

87.36%

seekgやclearでsegfaultになる

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,618

score 28

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

std::ifstream ifs("./a", std::ios::in|std::ios::binary);
while(1) {
  int64_t offset = ..;
  size_t size = ..;
  char buf[size];
  //ifs.clear();  //←これを追記してもここで落ちる(ifs.seekg(0, std::ios_base::beg)でも落ちる)
  ifs.seekg(offset, std::ios_base::beg);  //←ここでたまに落ちる
  if (ifs.read(buf, size)) {
    ..
  } else {
    ..
  }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • majiponi

    2019/09/01 00:12

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

    キャンセル

  • mentos109

    2019/09/01 00:15

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

    キャンセル

  • mentos109

    2019/09/07 23:42

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

    キャンセル

回答 4

+2

こんにちは。

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/04 22:11 編集

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

    キャンセル

  • 2019/09/06 00:28

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

    キャンセル

  • 2019/09/07 23:35 編集

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

    キャンセル

+1

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

#include <fstream>

int main()
{
    static std::ifstream ifs;
    ifs.open("./a", std::ios::in | std::ios::binary);
    while (1) {
        // ...
    }
    ifs.close();
}


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/06 15:13

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

    キャンセル

  • 2019/09/06 15:53

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

    キャンセル

  • 2019/09/06 19:16

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

    キャンセル

checkベストアンサー

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/31 16:24

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

    キャンセル

  • 2019/08/31 20:20

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

    キャンセル

  • 2019/08/31 22:06

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

    キャンセル

  • 2019/09/08 19:39

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/02 09:34

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

    キャンセル

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

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る