初めて書かせていただきます。失礼ありましたらご指摘ください。
VS2005でスタティックライブラリを作成しているのですが、
作成したライブラリが自身PC以外では動作しません。
リンクしたプロジェクトを実行すると、
rara.exe の 0x00401021 でハンドルされていない例外が発生しました:
0xC0000005: 場所 0x00137a40 に書き込み中にアクセス違反が発生しました。
と表示されとんでしまいます。
とぶ位置にはライブラリ関数があり、
その中は受け取った引数に数値を代入しているだけです。
リンク時に
honya.lib(honya.obj) : warning LNK4204: 'c:\honya\Debug\vc80.pdb' に
参照するモジュールのデバッグ情報がありません。
デバッグ情報を無視してオブジェクトをリンクします。
と表示されますが、コンパイルはできる状態です。
同じような症状を経験された方がいましたら教えてください。
問題解決に必要な情報が足りない場合もご指摘いただけますと助かります。
よろしくお願いします。
もともと、バグ(ポインターのアドレス異常?)があって
自分のPCでは、バグの参照先アドレスに運良く都合のいい値が入っていたのでは
スタック領域に、サイズの大きい変数をダミーで作ってみたら
自分のPCでも、同じ現象再現できるかも知れませんよ
リンク時に
honya.lib(honya.obj) : warning LNK4204: 'c:\honya\Debug\vc80.pdb' に
参照するモジュールのデバッグ情報がありません。
デバッグ情報を無視してオブジェクトをリンクします。
と表示されますが、コンパイルはできる状態です。
LIBを release版とdebug版で別にしてますか
返答ありがとうございます。
>もともと、バグ(ポインターのアドレス異常?)があって
>自分のPCでは、バグの参照先アドレスに運良く都合のいい値が入っていたのでは
指摘していただき、逆アセンブルで見てみた所、
ハングする関数の受け渡しをスタックから取得するところでとぶ状態のようです。
自分が書いたコードの、数値代入前にとんでいる様子で対処がさらにわかりません。
>スタック領域に、サイズの大きい変数をダミーで作ってみたら
>自分のPCでも、同じ現象再現できるかも知れませんよ
確認できませんでした。
>LIBを release版とdebug版で別にしてますか
LIBは提供先がまだdebug版での開発の為、debug版ライブラリでのみ作成しています。
>>ハングする関数の受け渡しをスタックから取得するところでとぶ状態のようで
す。
つまり、スタックから値を読み込むところでエラーが出ているという事のようですね。
この文章だとイマイチわからないのでいっそ周辺数行だけでも逆アセンブルリスト
を貼っていただけると判りやすいのですが、それはともかく。
1、ライブラリが読み取るのは「ポインタ」で、正しくないポインタが渡されている。
2、別環境で試す、というのがライブラリのみを持っていって別の場所でリンクして
いるため、自分の環境で再現しない。
3、デバッグ設定の違いでのスタック回りの検査内容が異なっていて、スタックがず
れている。
辺りでしょうか…。
そもそも「受け渡しをスタックから取得するところ」と書いているのにエラーが「書き
込み中にアクセス違反」な辺りからして矛盾している。
逆アセンブルが間違っていたり、OS側のエラーハンドラが壊れていない限り、これ
は無い筈なので、周辺リストとエラー報告の内容を照らし合わせる必要がある。
わかりづらくすみません。
>1、ライブラリが読み取るのは「ポインタ」で、正しくないポインタが渡されている。
ソース自体には不備がないだろうと見てもらった人にも確認が取れました。
なぜか正しくないポインタが渡されてるかもね。ともいわれましたが……。
>2、別環境で試す、というのがライブラリのみを持っていって別の場所で
> リンクしているため、自分の環境で再現しない。
「自分以外のPCで動作しません。」は自分のPCに
ライブラリをリンクし関数を呼ぶだけの、プロジェクトを作ったうえでの結論です。
同じようなプロジェクトを別PCで作成し、ライブラリをリンクすると、
今回相談している状態が起こってしまいます。
>3、デバッグ設定の違いでのスタック回りの検査内容が異なっていて、
> スタックがずれている。
これが一番怪しいのかもと思いましてプロジェクトのプロパティで設定を見直している
のですが、原因となるような部分をつかめていません。
ライブラリ生成側、リンク先共に、
ランタイムライブラリを/MDにする、呼び出し規約を__cdecl (/Gd)にする、
のところは注意していたのですが、他にも注目すべき設定はありますでしょうか。
聞いてばかりですみません。よろしくお願いします。
別PCで作成したと言うプロジェクトを自分のPCに丸ごと持ってきて
ビルドするとどうなるのか?
別PCで作成した実行ファイルを自分のPCに持ってきた場合は?
全く同じものでない限りは違う可能性があるわけで
検証するのであれば、そういう不安要素はとことん排除した方が良いと思います。
問題の関数だけを呼び出すような単純なプログラムで試しているのでしょうか?
スタックが破壊されているのでないならやはり引き渡したポインタがおかしいと言う
話は一番妥当だと思いますけれど。
単純なプログラムならここに公開しても多分大した量にはならないのではとも
思いますけれど。
返答遅くなりすみません。
長文になりますが、書かせていただきます。
>別PCで作成したと言うプロジェクトを自分のPCに丸ごと持ってきて
>ビルドするとどうなるのか?
>別PCで作成した実行ファイルを自分のPCに持ってきた場合は?
>全く同じものでない限りは違う可能性があるわけで
>検証するのであれば、そういう不安要素はとことん排除した方が良いと思います。
検証することとして抜けていました。ご指摘の事を行ったところ、
自分のPCでも同じ症状が出ることがわかりました。
>問題の関数だけを呼び出すような単純なプログラムで試しているのでしょうか?
はい。新規プロジェクトでwin32アプリケーションを選択して作成しただけの
プロジェクトで試していました。そのプロジェクトにライブラリをリンクし、
関数を呼ぶだけの状態です。
>スタックが破壊されているのでないならやはり引き渡したポインタがおかしいと言う
>話は一番妥当だと思いますけれど。
引き渡したポインタが指すアドレスは同一でした。
>単純なプログラムならここに公開しても多分大した量にはならないのではとも
>思いますけれど。
書いてみます。
typedef struct{
int mylocal;
int proc;
int authflag;
int rcnt;
int scnt;
int lcmd;
}TEST_INFO;
static TEST_INFO info;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
・
・
・
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MATSUI));
{
/*******************/
/* ライブラリ関数 */
/****************/
test_connect( &info );
}
・
・
・
return (int) msg.wParam;
}
/*************/
/* ライブラリ内 */
/****************/
int test_connect( INFO *info )
{
info->authflag = 0;
info->proc = 1;
info->rcnt = 0;
info->scnt = 0;
info->lcmd = 0;
return 0;
}
/* 逆アセンブル */
test_connect(&info);
00401088 push offset info (4081C8h)
0040108D call test_connect (401540h)
test_connect:
00401540 mov eax,dword ptr [esp+4]
00401544 xor ecx,ecx ※1
00401546 mov dword ptr [eax+8124h],ecx ※2
→0040154C mov dword ptr [eax+8120h],1 ※3
00401556 mov dword ptr [eax+8128h],ecx
0040155C mov dword ptr [eax+812Ch],ecx
00401562 mov dword ptr [eax+8130h],ecx
00401568 xor eax,eax
/* レジスタ */
※1
EAX = 004081C8 EBX = 00000000 ECX = 60A18A35 EDX = 0012FE22 ESI = 00000001
EDI = 00408CCC EIP = 00401544 ESP = 0012FDB4 EBP = 0012FF2C EFL = 00000202
※2
EAX = 004081C8 EBX = 00000000 ECX = 00000000 EDX = 0012FE22 ESI = 00000001
EDI = 00408CCC EIP = 00401546 ESP = 0012FDB4 EBP = 0012FF2C EFL = 00000246
004102EC = 00000100
※3
EAX = 004081C8 EBX = 00000000 ECX = 00000000 EDX = 0012FE22 ESI = 00000001
EDI = 00408CCC EIP = 0040154C ESP = 0012FDB4 EBP = 0012FF2C EFL = 00000246
004102E8 = 00000000
rara.exe の 0x00401546 で初回の例外が発生しました:
0xC0000005: 場所 0x004102ec に書き込み中にアクセス違反が発生しました。
※1~3の位置に⇒がある状態でのレジスタの状況です。
→の位置に⇒がきたときにアクセス違反のメッセージが出力されるようになりました。
プロジェクトのプロパティを操作したところエラーメッセージが変わってしまいました。
飛ぶ位置などに変わりはないのですが、現在元のメッセージにもどせておりません。
戻し次第また書かせていただきたいのですが、とりあえず現在の状態をかきます。
気づかれた点などありましたらご指摘お願いします。
>>0040154C mov dword ptr [eax+8120h],1 ※3
ここで8120hなんて馬鹿でかいオフセットが生成されるのが原因のようですね。
これ見る分にはなぜかグローバルにおいてあるinfoの方のオフセットが使われてい
るようですが…。
とりあえず、変な点を。
1、TEST_INFOという構造体を宣言しているのに、ライブラリ内ではINFOに名前
が変わっている。
2、「static TEST_INFO info;」と「int test_connect( INFO *info
)」が、何らかの理由で衝突している。
3、ライブラリの中と外で共通する構造体は同じヘッダファイルに記述して両方か
ら参照したほうが良い、と思う。
辺りでしょうか。
それと、
>>ランタイムライブラリを/MDにする、呼び出し規約を__cdecl (/Gd)にする、
>>のところは注意していたのですが
のに
>>参照するモジュールのデバッグ情報がありません。
とリンク時に警告が出ているのでしょうか?
なるほど、オフセットの値ですか……。
何をやって、そうなっているのかわからないですが。
>1、TEST_INFOという構造体を宣言しているのに、ライブラリ内ではINFOに名前
>が変わっている。
本来の名前ですと現在のプロジェクトなどが入っていたため、変更して
書かせていただきました。指摘していただいた部分は私のミスです。
実際動作しているプロジェクトではまったく同一の型になっております。
>2、「static TEST_INFO info;」と「int test_connect( INFO *info
> )」が、何らかの理由で衝突している。
何らかの理由がわかれば解決しそうですね。重点的に調べてみようと思います。
>3、ライブラリの中と外で共通する構造体は同じヘッダファイルに記述して両方か
>ら参照したほうが良い、と思う。
これも1と同じ理由で修正したために違う構造体になっておりますが、
実際のプロジェクトでは同じヘッダーファイルを見ています。
混乱させるようなことをしてすみません。
>>>ランタイムライブラリを/MDにする、呼び出し規約を__cdecl (/Gd)にする、
>>>のところは注意していたのですが
>のに
>>>参照するモジュールのデバッグ情報がありません。
>とリンク時に警告が出ているのでしょうか?
出ていました。現在はプロパティを修正して出ないようになっております。
あとはオフセットですね……。原因が分からなくても対処法なりが分かり次第
こちらに書かせていただきます。もし対処法などわかる方がいましたら
教えていただけますと助かります。
自分のところにあるきちんと動くものと
動かない物の間でソースレベルでの違いが無いかどうか確認を行ったでしょうか?
あるいはプロジェクトの設定に違いがないかどうかの確認は?
同じもので無いのであれば、動作に違いが出てもおかしくは無いはず。
と言う観点で調べて見てはどうですか?
ちなみに動かない環境へライブラリのみを持っていっているのであれば、
そのライブラリを使っているプロジェクトの設定は大丈夫でしょうか?
スタティックリンクライブラリを作成した時のプロジェクト設定と
ライブラリを使っている側のプロジェクト設定の間に矛盾点があれば、
おかしくなる可能性はあると思いますけれど。
自分のPCにある動くと言うプロジェクト一式を別PCに持っていって
リビルドして動く、自分のPC上の動くプログラムを別のPCへ持っていって
動くと言うのであれば、その別PCで作成した部分が益々怪しいと思います。
もっと順序だてて考えていかないと折角の苦労も無意味になってしまう事が
多々あります。
長らく返答できずすみませんでした。
時間切れによりライブラリをソースで提出して強引に動かしています。
問題の解決にならず残念です。
PATIOさんの言われているものは調べておりました。
残念ながらそれでもわからない状態でした。
問題の解決にはなっていませんがとりあえず解決済みとさせていただきます。
なにかつかみ次第ここに記すようにしますが、
時間がなく難しいと思います。
助言いただいたみなさま、お手数おかけしました。