BorlandC++ Compiler 5.5 でのDLL呼び出しでのエラー

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
HolyWings
記事: 12
登録日時: 13年前

BorlandC++ Compiler 5.5 でのDLL呼び出しでのエラー

#1

投稿記事 by HolyWings » 10年前

はじめて投稿します。よろしくお願いします。

開発環境は次の通りです。
OS : Windouws 7 (32bit)
使用言語 : C++
コンパイラ: GNU C++

今DirectXのDirectSound8を使用したDLLを作成しているのですが、2日ほどなんとかしようとしましたがどうしても
回避できない実行時のエラーがあります。

VisualC++ や GNU C++ や HSP で作成した実行ファイルからのDLLの呼び出し時には全くエラーは起こりませんが、
当方ではBorland C++ Compiler 5.5 で作成した実行ファイルからDLLの特定の関数を呼び出したときのみエラーが起き
強制終了してしまいます。

デバッグでエラー箇所を探ってみた所
IDirectSoundBuffer8::SetFX()メソッドでのエフェクトの設定時に起こることがわかりました。
しかもエフェクトにI3DL2 (Interactive 3D Audio Level 2) リバーブ エフェクトを設定した時のみ起こります。
他のエフェクト設定時には正常に動作します。

起こるエラーの種類はGNU のデバッガは"Program received signal SIGFPE, Arithmetic exception"といいます。
デバッガに表示されているアセンブラコードを見てみると
"fdivr QWORD PTR [ebp-0x8]"
このコードで止まっているので0除算だと思います。

あとデバッガに示しているエラーが起こっている具体的な場所は
IDirectSoundBuffer8::SetFX()メソッド内で呼び出されているWindows API のDllGetObjectClass()の内部で起こっています。

IDirectSoundBuffer8のメソッド内部でエラーが起きているためこれ以上の手出しが自分にはできません。

エラーが起きている仕組みが分かれば回避できると思うのですが、なかなか読み解けません。

なにか思い当たる方がいらっしゃればよろしくお願いします。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: BorlandC++ Compiler 5.5 でのDLL呼び出しでのエラー

#2

投稿記事 by ISLe » 10年前

HolyWings さんが書きました:デバッガに表示されているアセンブラコードを見てみると
"fdivr QWORD PTR [ebp-0x8]"
このコードで止まっているので0除算だと思います。
[ebp-0x8]というアドレスはスタックフレームでしょう。
何らかの理由でスタックが破壊されて、浮動小数点数として正しくない値にアクセスしている可能性はないでしょうか。

そもそもBorland C++ Compiler 5.5はいまとなってはC++の規格に対する準拠度が非常に低いので、浮動小数点数演算に対する扱い等が異なる可能性もあります。

アバター
HolyWings
記事: 12
登録日時: 13年前

Re: BorlandC++ Compiler 5.5 でのDLL呼び出しでのエラー

#3

投稿記事 by HolyWings » 10年前

ISLe 様 返信ありがとうございます。
ISLe さんが書きました:[ebp-0x8]というアドレスはスタックフレームでしょう。
何らかの理由でスタックが破壊されて、浮動小数点数として正しくない値にアクセスしている可能性はないでしょうか。
スタックフレームの事まで思い至りませんでした。
なんらかの手がかりになるような気がします。
これを足がかりにしてもう少し解析を進めたいと思います。

アドバイスいて頂きありがとうございました。

アバター
HolyWings
記事: 12
登録日時: 13年前

Re: BorlandC++ Compiler 5.5 でのDLL呼び出しでのエラー

#4

投稿記事 by HolyWings » 10年前

いろいろ試したところBorland C++ Compiler 5.5で作成した実行ファイルから
IDirectSoundBuffer8::SetFX()メソッドでI3DL2 (Interactive 3D Audio Level 2) リバーブ エフェクトを設定
すると実行時にエラーが起こるという結論に達しました。

他のエフェクトを設定してもエラーが起こらないのですがI3DL2 (Interactive 3D Audio Level 2) リバーブ エフェクトを設定
したときのみエラーが起こります。

コンパイラが作成するコードとの相性が良くないとしかいいようがありません。
確信に達したテストコードを乗せます。

コード:

#include <iostream>
#include <windows.h>
#include <dsound.h>

using namespace std;

LPDIRECTSOUND8 gDS;
LPDIRECTSOUNDBUFFER8 gDSBuffer;
LPDIRECTSOUNDBUFFER gDSPrimary;

#define SAFE_RELEASE( p ) if( (p) != 0 ){ (p)->Release() ; (p) = NULL;}

bool init();
void end();
bool setEffect();

//------------------------------------------
//初期化処理関数
//------------------------------------------
bool init()
{
	//エフェクトを使用するので呼び出す必要あり
	CoInitialize( NULL );
	
	//IDirectSound8インスタンスの取得
	HRESULT hr = DirectSoundCreate8( NULL , &gDS , NULL );
	
	//成功した?
	if( hr != DS_OK )
	{
		return false;
	}
	
	//協調レベルの設定
	hr = gDS->SetCooperativeLevel( GetDesktopWindow() , DSSCL_NORMAL );
	
	//成功した?
	if( hr != DS_OK )
	{
		SAFE_RELEASE( gDS );
		
		return false;
	}
	
	//---------------------------
	//プライマリバッファの作成処理
	//---------------------------
	DSBUFFERDESC desc ={};
	
	desc.dwSize = sizeof( desc );
	desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
	
	//プライマリバッファの作成
	hr = gDS->CreateSoundBuffer( &desc , &gDSPrimary , NULL );
	
	//成功した?
	if( hr != DS_OK )
	{
		end();
		return false;
	}
	//--------------------------
	//サウンドバッファの作成処理
	//--------------------------
	WAVEFORMATEX fmt={};
	
	fmt.wFormatTag = WAVE_FORMAT_PCM;
	fmt.nChannels = 2;
	fmt.nSamplesPerSec = 22050;
	fmt.wBitsPerSample = 16;
	fmt.nBlockAlign = 4;
	fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
	fmt.cbSize = 0;
	
	desc.dwSize = sizeof( desc );
	desc.dwFlags = DSBCAPS_CTRLFX;
	desc.lpwfxFormat = &fmt;
	desc.dwBufferBytes = fmt.nAvgBytesPerSec;
	
	LPDIRECTSOUNDBUFFER pBuffer;
	
	//サウンドバッファの作成
	hr = gDS->CreateSoundBuffer( &desc , &pBuffer , NULL );
	
	//成功した?
	if( hr != DS_OK )
	{
		end();
		return false;
	}
	
	//IDirectSoundBuffer8インスタンスの取得
	hr = pBuffer->QueryInterface( IID_IDirectSoundBuffer8 , (VOID**)&gDSBuffer );
	
	//もう必要ないので解放する
	pBuffer->Release();
	
	//成功した?
	if( hr != DS_OK )
	{
		end();
		return false;
	}
	
	
	return true;
}
//-------------------------------
//終了処理関数
//-------------------------------
void end()
{
	SAFE_RELEASE( gDSBuffer );
	SAFE_RELEASE( gDSPrimary );
	SAFE_RELEASE( gDS );
}

//---------------------------------
//エフェクトの設定関数
//---------------------------------
bool setEffect()
{
	DSEFFECTDESC desc ={};
	
	desc.dwSize = sizeof( desc );
	//このエフェクトの設定で実行時のエラーになります。
	//これ以外のエフェクトではエラーが起こりません。
	desc.guidDSFXClass = GUID_DSFX_STANDARD_I3DL2REVERB;
	
	HRESULT hr ;
	DWORD ret;
	
	//エフェクトを設定。※ここでエラー発生
	hr = gDSBuffer->SetFX( 1 , &desc , &ret );
	
	//成功した?
	if( hr != DS_OK )
	{
		return false;
	}
	
	return true;
}

int main()
{
	if( init() )
	{
		cout << "初期化 成功" << endl;
	}
	else
	{
		cout << "初期化 失敗" << endl;
	}
	
	if( setEffect() )
	{
		cout << "エフェクト設定 成功" << endl;
	}
	else
	{
		cout << "エフェクト設定 失敗" << endl;
	}
		
	end();
	
	return 0;
}
答えがはっきりしたので解決とさせていただきます。

閉鎖

“C言語何でも質問掲示板” へ戻る