Borlandの罠

本日(というよりは昨日)13時間無駄にした時の話

まずはこのコードを見てもらいたい
#include <windows.h>
#include <stdio.h>
long WINAPI exep(EXCEPTION_POINTERS *pep){
return EXCEPTION_CONTINUE_EXECUTION;
}
int main(){
SetUnhandledExceptionFilter(exep);
printf(“mainn”);
RaiseException(0x00000000,0,0,NULL);
printf(“main2n”);
return 0;
}

これはC言語からWin32APIの機能を使って例外処理を行うサンプルで
SetUnhandledExceptionFilter関数にてexepを例外処理関数に設定し、exepでは何もせず即例外位置に復帰するだけのプログラム。

ここで問題なのが、上のコードを手元のbccコンパイラでコンパイルするとINVALID DISPOSION例外を吐いて動作しないこと。

最初は何かしら必須な処理を怠ったせいかと思いサンプルコードを大量に引っ張ってきたり、関連知識がありそうな友人に片っ端から相談したが一向に原因が掴めず
最小コードをこねくり回している最中に、間違えてVCコンパイラでコンパイルしたことから原因判明。
要するに「BCCコンパイラだからエラーしている」というもの。

理由:
BCCコンパイラがmain関数前にSEH連鎖の0番に設定する関数でエラーしている。
(SEH連鎖:例外処理関連で呼ばれる関数、数珠繋ぎにいくつも設定できる)

で、OS自体が用意してくれる関数を使っているうちは問題ないのでBCCさんの独自関数にはどいてもらうことにする。
具体的にはこんなコード
#ifdef __BORLANDC__
__asm{
push EAX
mov EAX,DWORD PTR FS:[0]
mov EAX,DWORD PTR DS:[EAX]
mov DWORD PTR FS:[0],EAX
pop EAX
}
#endif
SEH連鎖1番のアドレスを取ってきて0番に上書きするだけ
ただC言語上からアクセスする方法が自分の知る範囲では存在しないのでインラインアセンブラの力を借りてます。

無料版にインラインアセンブラやらを無理やり突っ込んだものを使っているので、普通のBCC環境とは微妙に違っているのが原因か?
もし有料の最新版でも発現するバグなら割と大事だがどうだろう。
コンパイラ自体がわざわざ自家製の関数を突っ込んでいるのだから何かしら意味があるのかもしれないが、VCでは不便していないのでこのまま行くことにする。

さて、これで例外報告機能も復旧できたし、今度こそth105_aiで0.80に向けた作業に……