Zerostringでのメモリ確保について

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
庄司

Zerostringでのメモリ確保について

#1 投稿記事 by 庄司 »

Zerostringについてお聞きします。

文字列が返るAPIを使う時に予めメモリを確保するのに使う事と、
使わなくてもなぜか平気だったりするが、実は良くないのというのは
なんとなくわかりました。

では以下の場合はどうなるのでしょう。

コード: 全て選択


Dim buffer As String

a=色々計算しstring型にしたもの
buffer = a

b=色々計算しstring型にしたもの
buffer = buffer + a
 ・
 ・cを追加で足す、dを追加で足すという感じで繰り返し
 ・
最終的にbufferをテキストファイルに書き込む
文字列が返るAPIは使って無いのですが、
こういう場合もbufferはZerostringでメモリ確保する必要があるのでしょうか?
その時は勝手にメモリを確保してくれるのでしょうか?
(予め確保しなければならない場合、バイト数が最終的な所でしか
分からないのですがその時は多めに確保しておくのでしょうか?)

それと自分でプロシージャ(Function)を作って、
戻り値がstring型の場合はどうなのでしょうか?

さらに、一度確保すれば、その後もずっと有効なのでしょうか?
無効になるとすればどんな時なのでしょうか。

確保されてないと必ず作ったソフトが落ちるとか、
コンパイルできないとかなら自分で試せばよいのですが、
普通にコンパイルは通るし、いつも必ず落ちる訳ではないし
(関係ないと思ってたファイルオープンダイアログを開いた時に、急に落ちたり)、
デバッグでも何もでないので一体何が起こってるのか分からないのです。
(色々いじってバグが出なくなって安心してると、出たりする)

検索しても役立つ情報がなく困っています。
なのでZerostringはどういうときに必要でどのように使うのか、
なぜ使わなくても作ったソフトが普通に使えたりするのか教えてください。
長文ですみませんが、どうか、宜しくお願いします。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: Zerostringでのメモリ確保について

#2 投稿記事 by hira »

文字列が返るAPIは使って無いのですが、
こういう場合もbufferはZerostringでメモリ確保する必要があるのでしょうか?
その時は勝手にメモリを確保してくれるのでしょうか?
この場合はする必要はありません。
ABのString型は、文字列の代入などのときには自動でメモリが確保される仕組みになっています(このために通常はメモリの概念を知る必要はありません)。
それと自分でプロシージャ(Function)を作って、
戻り値がstring型の場合はどうなのでしょうか?
これも通常の代入処理と同じ扱いになる(はず)なのでZeroStringを使わなくて問題ないです。
さらに、一度確保すれば、その後もずっと有効なのでしょうか?
無効になるとすればどんな時なのでしょうか。
基本的には、そのString型の宣言場所によります。プロシージャの外であればプログラム終了まで、プロシージャの中であればそのプロシージャから抜けるまで、クラスの中であればクラスが生きている限り…という感じです。
検索しても役立つ情報がなく困っています。
なのでZerostringはどういうときに必要でどのように使うのか、
なぜ使わなくても作ったソフトが普通に使えたりするのか教えてください。
長文ですみませんが、どうか、宜しくお願いします。
ZeroStringは文字列関係のAPIを使うときに必要になります。
(正確にいえば、何らかの方法でメモリを確保すればよいので絶対ZeroString、というわけではありません)
APIはメモリの確保を担当していませんので、こちらでメモリを用意してやる必要があります。このときに使うのがZeroStringというわけです(意味不明?)。
庄司

Re: Zerostringでのメモリ確保について

#3 投稿記事 by 庄司 »

hiraさん、大変分かり易い解説有難うございます。
基本的には、そのString型の宣言場所によります。プロシージャの外であればプログラム終了まで、
プロシージャの中であればそのプロシージャから抜けるまで、クラスの中であればクラスが生きている限り…という感じです。
一度やれば保持されるのですね。文字列を得る度にZerostring使ってました。
でも、MakeStrを使ったりすると文字列の長さにあわせて確保領域が縮まるみたいですね。
(デバッグでなんか出たので、たぶんそうだと思う。)

さらに質問なのですが、GetTimeFormatやGetPrivateProfileString等、
文字列取得と同時に文字列のバイト数を指定するものは、
そのバイト数のメモリを自動で確保してくれるのでしょうか?
それともここで指定するバイト数はまた別の物なのでしょうか?
度々すいませんが、どうか宜しくお願いします。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: Zerostringでのメモリ確保について

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

> さらに質問なのですが、GetTimeFormatやGetPrivateProfileString等、
> 文字列取得と同時に文字列のバイト数を指定するものは、
> そのバイト数のメモリを自動で確保してくれるのでしょうか?
> それともここで指定するバイト数はまた別の物なのでしょうか?

そこで指定するバイト数は予めZeroStringに指定した値と同じものを渡します。
そうして書き込める最大のバイト数を伝えているのです。

WindowsはABのString型のことなど知らないので、
こちらがWindowsに代わってZeroStringを呼んで文字列の領域を用意するというわけです。
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#5 投稿記事 by マティ »

マティです。hiraさんイグトランスさんの補足をします。

Zerostringで取得した領域は、使用不能(hiraさんが説明)になるまで有効です。
また、Zerostringで指定した文字(バイト)数+NULL分の領域を自動的に確保します。

MakeStr関数は、他の方式でメモリーを確保した場合に使用します。

※ポインターで示すメモリー内のNULL(0)までのデータを、ABが自動的に作成するString型にコピーする事により作成する特殊な処理です。String型には適用しない方が良いと思います。
庄司

Re: Zerostringでのメモリ確保について

#6 投稿記事 by 庄司 »

マティさん、イグトランスさん返信ありがとうございます。

文字列取得と同時に文字列のバイト数を指定するものでも
ZeroStringでメモリ確保しないといけないのですね。

>Zerostringで指定した文字(バイト)数+NULL分の領域を自動的に確保します。
Win32プログラミング講座 ~ Step11. テキスト エディタを作るでは
文字列のバイト数を取得した後、+1でZerostringを使ってるのですが、
これはNULL分は自動的に確保されないから1を足してるのだと思ってました。
では、この+1は、どういうことなのでしょう?

コード: 全て選択


以下コピペ
'EditBox1のハンドルを取得
hEdit=GetDlgItem(hMainWnd, EditBox1)

'テキスト データを格納するためのバッファ領域を確保
length=GetWindowTextLength(hEdit)
buffer=ZeroString(length+1)

'テキスト バッファを取得
GetWindowText(hEdit, buffer, length+1)
>MakeStr関数は、他の方式でメモリーを確保した場合に使用します。
>※ポインターで示すメモリー内のNULL(0)までのデータを、ABが自動的に作成するString型に
>コピーする事により作成する特殊な処理です。String型には適用しない方が良いと思います。
全然知らなかったです。
GetWindowTextで取得した文字列終端のNULL文字を取るのに使ってました。
これからはLeft$を使う事にします。
マティ
記事: 161
登録日時: 2005年8月23日(火) 00:15
お住まい: 沖縄県
連絡する:

#7 投稿記事 by マティ »

インクルードファイル(string.sbp)内で以下の様に定義されています。

コード: 全て選択


Function ZeroString(length As DWord) As String
	Dim pByte As *Byte

	'バッファ領域を確保
	_System_HeapStringFree(StrPtr(ZeroString))
	pByte=_System_HeapStringAlloc(length)
	SetDWord(VarPtr(ZeroString),pByte)
End Function
文字列変が使用する最大領域が決まっているなら、(ZeroString以外の)関数を使用した領域確保をお進めします。

APIは使用者責任で領域を確保する必要がありますので、自身で領域を明示的に確保して下さい。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: Zerostringでのメモリ確保について

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

> >Zerostringで指定した文字(バイト)数+NULL分の領域を自動的に確保します。
> Win32プログラミング講座 ~ Step11. テキスト エディタを作るでは
> 文字列のバイト数を取得した後、+1でZerostringを使ってるのですが、
> これはNULL分は自動的に確保されないから1を足してるのだと思ってました。
> では、この+1は、どういうことなのでしょう?
AB(というよりWinAPIが主に想定しているC/C++)の文字列は、文字列の終端にその印(Chr$(0))を1文字置いてあります。
なのでその分のメモリもあるので+1しているわけです。
ただしマティさんが仰っているとおりZeroStringはそれを考慮しているので、ZeroStringの引数では+1する必要はありません。
今回の場合ではGetWindowTextだけに+1が必要です。

> >MakeStr関数は、他の方式でメモリーを確保した場合に使用します。
> >※ポインターで示すメモリー内のNULL(0)までのデータを、ABが自動的に作成するString型に
> >コピーする事により作成する特殊な処理です。String型には適用しない方が良いと思います。
> 全然知らなかったです。
> GetWindowTextで取得した文字列終端のNULL文字を取るのに使ってました。
> これからはLeft$を使う事にします。
私はこれを行っても全然問題ないと思っています。
String型は読み取りしか行わなければBytePtr型の引数に与えられます。
MakeStrもBytePtr型を引数に取り、その引数からは文字列を読み取るだけなので、上に当てはまり問題ないと考えています。
(GetWindowTextのようにそこへ書き込みを行うとなるとこのようにややこしいことになるのですが)

#読み返すとますます混乱させてしまいそうになっていますが。
庄司

Re: Zerostringでのメモリ確保について

#9 投稿記事 by 庄司 »

イグトランスさん、マティさん返信ありがとうございます。

だんだん難しくなってきましたが、
とにかくZeroStringは+1分確保してくれる事が分かりましたし、
(Win32プログラミング講座のサンプルが間違ってる事もあるんですね)
MakeStrは読み取るだけなら使っても良いという事も分かりました。


凄く勉強になりました。
イグトランスさん、マティさん、hiraさん、ありがとうございました。
返信する