« MinGW + WinSock | トップページ | 時々突然落ちますけど…その2 »

2015年2月10日 (火)

時々突然落ちますけど…その1

では、そろそろ試用版をリリースしてみようかな、と思ったのですが…しばらく使っていると突然落ちてしまいます。
cygwinのターミナルには"Segmentation Fault"と表示されてます(^-^;

タイミング的にまちまちなので「ああスレッド関係だろうな」という感じではあるのですが、マルチスレッドプログラミングの勘がまだまだ働かないので通常のデバッグを試みました。

まず、debugバージョンの実行モジュールをビルドします。で、gdbを起動し、runを実行しました。

メインスレッド
入力デバイス(キーボード/マウス)用スレッド
グラフィックス描画用スレッド
サウンド再生用スレッド

などなどが起動されるところまでは確認できますが、WinSockによるネットワーク接続の確立で失敗します。gdbからではなく普通にdebugバージョンを起動すると接続できるので、gdb内からの実行だとWinSock関連で失敗してしまうようです。

"Segmentation Fault"が発生するのは、ネットワーク接続完了後なのでこれではデバッグできません。

いわゆるprintfデバッグも考えましたが、非常に大量のログが出ることは予想できたのでなんとかならないかなぁとgoogleさん頼みで検索していました。

探しながら気がついたのは、"Segmentation Fault"という文字列が表示されているという点です。

ということはSIGSEGVというシグナルが捕捉されていてデフォルトハンドラで文字列が表示されているということですよね。だったら、ハンドラを自分で書いて、ハンドラ内でPCレジスタをなんとかして調べられるはずだから、プログラムのどこらへんで例外が起こったのかは分かりそうだという発想でした。

早速googleさんで調べます。

"mingw catch sigsegv"

で探しだしたのがこちらのページです。優秀な技術者さんに感謝ですね。

http://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c/

こちらのページではUNIX/Linux/MinGWで例外を捕捉し、"addr2line"というユーティリティーを利用して
例外発生時のStack Traceの情報を出来る限り表示するというものです。うまくいけばソースコードのファイル名、行数を表示してくれます。

こちらにあるサンプルソースコードを自分のソースコードのmain.cppあたりにコピーして少し手直しすればそのまま使えます。但し、スタックトレースを順次表示するためにsystem()を実行するため、cygwinターミナル内で実行するとコマンドプロンプトウィンドウが開いては閉じ、開いては閉じするだけで結果が見られないので、関数addr2line()の中のsprintf()の直後にaddr2line_cmdの内容を標準出力させるように変更しました。

実際にはこの標準出力をコピペして手動で実行しました。こんな感じです。
qtbrynhildr.exeは実際はフルパスですが…(cygwinなので"/"にしてます)

#!/bin/bash
addr2line -f -p -e debug/qtbrynhildr.exe 74b2b5f0
addr2line -f -p -e debug/qtbrynhildr.exe 00c8f142
addr2line -f -p -e debug/qtbrynhildr.exe 00d5bca2
addr2line -f -p -e debug/qtbrynhildr.exe 00ce0f6f
addr2line -f -p -e debug/qtbrynhildr.exe 00ce5ce6
addr2line -f -p -e debug/qtbrynhildr.exe 00ce4ee5
addr2line -f -p -e debug/qtbrynhildr.exe 00cfb5d9
addr2line -f -p -e debug/qtbrynhildr.exe 0041cdae
addr2line -f -p -e debug/qtbrynhildr.exe 00406a61
addr2line -f -p -e debug/qtbrynhildr.exe 0a5af282
addr2line -f -p -e debug/qtbrynhildr.exe 0a6b3788
addr2line -f -p -e debug/qtbrynhildr.exe 0a6b88eb
addr2line -f -p -e debug/qtbrynhildr.exe 0a57df61
addr2line -f -p -e debug/qtbrynhildr.exe 0a57dde5
addr2line -f -p -e debug/qtbrynhildr.exe 6b929eee
addr2line -f -p -e debug/qtbrynhildr.exe 0a8c6af1
addr2line -f -p -e debug/qtbrynhildr.exe 0a5a7cfa
addr2line -f -p -e debug/qtbrynhildr.exe 0a5842fd
addr2line -f -p -e debug/qtbrynhildr.exe 0a5835dd
addr2line -f -p -e debug/qtbrynhildr.exe 0a59fc58
addr2line -f -p -e debug/qtbrynhildr.exe 0a5af7c3
addr2line -f -p -e debug/qtbrynhildr.exe 0a6cb790
addr2line -f -p -e debug/qtbrynhildr.exe 0a57df61
addr2line -f -p -e debug/qtbrynhildr.exe 0a57dde5
addr2line -f -p -e debug/qtbrynhildr.exe 6b929eee
addr2line -f -p -e debug/qtbrynhildr.exe 6b9cf5e7
addr2line -f -p -e debug/qtbrynhildr.exe 6b92b0a6
addr2line -f -p -e debug/qtbrynhildr.exe 6b92ab8e
addr2line -f -p -e debug/qtbrynhildr.exe 6285cf11
addr2line -f -p -e debug/qtbrynhildr.exe 6b978658
addr2line -f -p -e debug/qtbrynhildr.exe 76b08e71
addr2line -f -p -e debug/qtbrynhildr.exe 76b090d1
addr2line -f -p -e debug/qtbrynhildr.exe 76b0a66f
addr2line -f -p -e debug/qtbrynhildr.exe 76b0a6e0
addr2line -f -p -e debug/qtbrynhildr.exe 6b979c99
addr2line -f -p -e debug/qtbrynhildr.exe 6285cdf0
addr2line -f -p -e debug/qtbrynhildr.exe 6b927f94
addr2line -f -p -e debug/qtbrynhildr.exe 6b92822f
addr2line -f -p -e debug/qtbrynhildr.exe 6b92a53d
addr2line -f -p -e debug/qtbrynhildr.exe 00b66520
addr2line -f -p -e debug/qtbrynhildr.exe 0a57b357
addr2line -f -p -e debug/qtbrynhildr.exe 0040182a
addr2line -f -p -e debug/qtbrynhildr.exe 004145eb
addr2line -f -p -e debug/qtbrynhildr.exe 0041e0ad
addr2line -f -p -e debug/qtbrynhildr.exe 004013de
addr2line -f -p -e debug/qtbrynhildr.exe 749f7c04
addr2line -f -p -e debug/qtbrynhildr.exe 7706b90f
addr2line -f -p -e debug/qtbrynhildr.exe 7706b8da

これを実行すると以下の出力が得られました。

?? ??:0
?? ??:0

中略

?? ??:0
?? ??:0
_ZN8QPainter10drawPixmapEiiRK7QPixmap at C:/Tools/develop/Qt/Qt5.3.2/5.3/mingw482_32/include/QtGui/qpainter.h:786
_ZN11qtbrynhildr10MainWindow10paintEventEP11QPaintEvent at D:\home\xxxxxxx\Src\qtbrynhildr\src/mainwindow.cpp:130
?? ??:0
?? ??:0

 中略

?? ??:0
_Z5qMainiPPc at D:\home\xxxxxxx\Src\qtbrynhildr\src/main.cpp:92
WinMain@16 at c:\work\build\qt5_workdir\w\s\qtbase\src\winmain/qtmain_win.cpp:131
?? at fake:?
?? at crtexe.c:?
?? ??:0
?? ??:0
?? ??:0

2箇所の情報が得られました。2つ目はmain.cppなので、手がかりになりそうなのは1つ目の情報だけのようです。

mainwindow.cppの130行目は…

// paint event
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0, 0, *pixmap);  <== ここ
}

となっています。デスクトップ画像を表示するためのdrawPixmap関数を呼び出した先のどこかでどうやら例外が起こっているようです。

長くなったので"その2"に続きます。

« MinGW + WinSock | トップページ | 時々突然落ちますけど…その2 »

コメント

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: 時々突然落ちますけど…その1:

« MinGW + WinSock | トップページ | 時々突然落ちますけど…その2 »