自前で定義したstrstr関数の戻り値

ActiveBasicのバグと思われる不具合を発見された方は、こちらから知らせていただけると助かります。
返信する
メッセージ
作成者
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

自前で定義したstrstr関数の戻り値

#1 投稿記事 by hira »

またCランタイム関数に関する話題です(^^;;

コード: 全て選択

#strict
#prompt
Declare Function strstr CDECL Lib "crtdll" (s1 As *Byte,s2 As *Byte) As *Byte
Dim a As *Byte,b As *Byte
a="12345678"
b=strstr(a,"456")
Print b As DWord-a As DWord
このコードで、とんでもない値がPrintされてしまいます。
strstr関数の戻り値(変数b)は ポインタ or NULL となるはず(ここではポインタが返ることを期待したコード)なのですが、なぜか1が返ってきています。さらに、*ByteからLongに強制変換されているという警告も出ました。
CDECLだからかな、と思ったのですが

コード: 全て選択

#strict
#prompt
Declare Function strtok CDECL Lib "crtdll" (s1 As *Byte,s2 As *Byte) As *Byte
Dim a As *Byte,b As *Byte
a="123 45678 90123"
b=strtok(a," ")
While b<>NULL
	Print MakeStr(b)
	b=strtok(NULL," ")
Wend
こちらはなぜか問題ありません。
同じようにポインタを返すCDECL関数なのに、strstrだけおかしいのはなぜでしょう…?
Ver 4.13.00では問題なく動作していたので不具合でしょうか?

Ver 4.22.00 Windows XP Home (SP2) で確認。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#2 投稿記事 by イグトランス »

"crtdll"だけでなく"msvcr71", "msvcr70"で試してみましたが同じくだめでした。

しかしNULLポインタは正しく返ってきます。

コード: 全て選択

#strict
#prompt
Declare Function strstr CDECL Lib "crtdll" (s1 As *Byte,s2 As *Byte) As *Byte
Dim a As *Byte, b As *Byte
a="12345678"
b=strstr(a, "d")
If b = NULL Then
	Print "NULL"
EndIf
また、_mbsstrでは問題ありません。

コード: 全て選択

#strict
#prompt
Declare Function _mbsstr CDECL Lib "crtdll" (s1 As *Byte,s2 As *Byte) As *Byte
Dim a As *Byte, b As *Byte
a="12345678"
b=_mbsstr(a, "456")
If b = NULL Then
	Print "NULL"
Else
	Print MakeStr(b)
EndIf 
同じくVer 4.22.00 Windows XP Home (SP2)です。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

#3 投稿記事 by NoWest »

> "crtdll"だけでなく"msvcr71", "msvcr70"で試してみましたが同じくだめでした。

私の方でも同様の問題が発生します。

気になったのは、strstrは戻り値が*Charの筈なのにデバッガはLongになっていると文句を言っていることですね。

そもそも、ポインタもCPUが64bitで無い限りはLong型と同サイズなので
Long型になっているという警告が出ても動かないことは無いでしょうが、
同様の形式で定義されている_mbsstrの方は*Byteでちゃんと定義されているみたいです。
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#4 投稿記事 by 山本 »

function.sbpでstrstr関数が定義されており、そちらの関数を呼び出してしまっているのが原因のようです。
本来であれば、関数定義の重複エラーという扱いになるので、この点に関しては次回のバージョンアップで修正しようと思います。

そして問題となるのが、Cの標準ライブラリとして定義されている各関数をどのように実装していくかというポイントです(msvcrt.dllをDeclareするという手法での実現を検討中です)。

汎用性の面ではcrtdll.dllも良さそうなのですが、こちら、Win64での動作確認が取れませんでした(泣

msvcrt.dllであればWindows95から入っているみたいですし、Win64の環境での動作も実証できています(バージョン差異による細かい弊害が心配ですけど…)。ここれらへんの詳細事項をご存知の方、アドバイスいただけると助かります。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#5 投稿記事 by イグトランス »

建前としてはMSVCRT.DLLはWindowsシステム内部の物なので,
アプリケーションが勝手に使ってはいけないらしいです。
http://msdn.microsoft.com/library/ja/vc ... raries.asp

そうは言ってもMinGWというC/C++コンパイラは今も使っていますし,
単純に使うだけならバージョンの違いも気にする必要は無いでしょうし,
ありがたい存在であることには違いありません。
#だからこそ悩ましい。
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#6 投稿記事 by 山本 »

イグトランス さんが書きました:建前としてはMSVCRT.DLLはWindowsシステム内部の物なので,
アプリケーションが勝手に使ってはいけないらしいです。
http://msdn.microsoft.com/library/ja/vc ... raries.asp

そうは言ってもMinGWというC/C++コンパイラは今も使っていますし,
単純に使うだけならバージョンの違いも気にする必要は無いでしょうし,
ありがたい存在であることには違いありません。
#だからこそ悩ましい。
こういう情報もあったんですね!下記のように整理してみました。

・msvcrt.dll … MS製Cランタイムライブラリ(システムDLL)
・msvcrt40.dll … VC6.0用Cランタイムライブラリ
・msvcr71.dll … VC.NET用Cランタイムライブラリ
・msvcp71.dll … VC.NET用C++ランタイムライブラリ

バージョン差異に関しては、Cランタイムリソースを相互で扱う場合に不具合が生じる可能性があるようです。たとえば、strstr関数のような、単なるポインタやバッファをやり取りする関数は良いのですが、ファイル操作の関数やスレッド生成の関数なんかは、各DLL間で汎用性が低そうです。

同一EXE内でこれらのCRT DLLを扱う場合は良いのですが、何らかの外部DLLと自作EXEを組み合わせて活用する場合に問題が生じそうです…。

一番良いのは、ABライブラリでCRTの内容をリバースエンジニアリングしてしまうことなのですが、、、これはこれで労力がかかります。

結局、私の意見をまとめますと、下記のようになります。

バージョン差異による問題がおきそうにない関数をリストアップし、それらをインストール率が一番高そうなmsvcrt.dllからリンクしてしまい、その他に関しては、独自のライブラリでカバーする。

いかがでしょうか?
返信する