1つ目の質問に関しては、問題ないということですね。安心しました。
2つ目の質問に関しては、アドレスが変わらない保証はないが、確保したサイズは保障されているということですね。
ためしにmalloc命令とfree命令を作ってみました。アドレスが変わらないことが保障されていれば、このスクリプトをつかおうと思っていましたが、変わりうるのであれば、作り直そうと思います。
ご回答いただき、ありがとうございました。
2つ目の質問に関して、きっぱりとアドレスが変わりうる・変わらないという回答がもらえていないのでしばらくは未解決状態にしますが、しばらく回答がつかなければ、解決といたします。
このスクリプトを実行すると、malloc命令とfree命令の呼び出しをボタンで操作します。
左下の入力ボックスは確保ボタンを押したときに確保される領域の大きさです。
右の文字はモジュール内部の各領域の状態です。ptrは領域のアドレス、flagは使用中かのフラグ、sizeは領域のサイズです。
/*
このモジュールはC言語のmalloc関数とfree関数のような命令を提供します。
malloc int p1
サイズがp1以上の領域を確保し、そのアドレスを返します。
なお、C言語と異なり、領域の確保に失敗した場合の動作は未定義です。
free int p1
mallocで確保された領域p1を解放します。
戻り値は解放処理が成功した場合0が返ります。p1がnullの場合は無条件に0が返ります。
失敗した場合は負の値が返ります。戻り値が-2の場合、二重解放の可能性があります。
*/
#module "HK2mmem"
#define INITBUFCNT 8
#define INITBUFSIZE 64
#define BUFEXPANDORDER 8
/*
定数
INITBUFCNT 起動時の領域の数
INITBUFSIZE 確保時の初期領域サイズ
DEFBUFEXPANDORDER 領域数を増やすときの単位
*/
sdim sbuf,64,1//割り当てられる要素を持つ配列
dim bflag,1//要素が割り当てられているかのフラグ。0なら未割当、1なら割り当て済み。
dim isize,1//要素の領域サイズ。
#deffunc local autoinit
sdim sbuf,64,INITBUFCNT
dim bflag,INITBUFCNT
dim isize,INITBUFCNT
repeat length(isize)
isize(cnt)=INITBUFSIZE
loop
return
#deffunc malloc int p1
len=length(sbuf)//領域数
match=-1//割り当てる領域の要素番号
start=0//高速化とコードの簡素化のためのループの初期値(サブルーチンの引数)
ret=0//戻り値(サブルーチンの局所変数でもある)
max=0//最大値(サブルーチンの局所変数)
min=0//最小値(サブルーチンの局所変数)
logmes strf("malloc:割り当て処理が開始されました")
if(p1<0){
ret=0
}else{
gosub *getSuitableBufferNo//既存の領域から割り当てに適当な領域の要素番号を検索する
if(stat<0){//適当な領域が見つからなかった場合
logmes strf("malloc:適当な領域が見つかりませんでした。")
gosub *expandBufferCnt//領域数を拡張する
match=len
}else{//適当な領域が見つかった場合
match=stat
logmes strf("malloc:%dが適当です\nmalloc:割り当て処理は終了しました",match)
}
gosub *allocateBuffer//領域を割り当てる
if(stat==0){//割り当てに成功した場合
ret=varptr(sbuf(match))//領域のアドレスを返す
}else{
ret=0
}
}
return ret
*getSuitableBufferNo//既存の領域から適当な領域の要素番号を返す
gosub *searchEmpty//空き領域を検索する
if(stat==-1){//空き領域が存在しない場合
logmes strf("suit:空き領域は見つかりませんでした")
ret=-1
}else{//空き領域が存在する場合
start=stat
logmes strf("suit:最初の空き領域は%dです。",start)
gosub *searchFirstFit//先頭一致する領域を検索する
if(stat==-1){//十分な大きさの空き領域が存在しない場合
logmes strf("suit:十分な大きさの空き領域はありませんでした。")
gosub *searchLargestEmpty//最も大きな空き領域を検索する
ret=stat
logmes strf("suit:最も大きな空き領域は%dです。",ret)
}else{//十分な大きさの空き領域が存在する場合
start=stat
logmes strf("suit:十分な大きさの空き領域は%dです。",start)
gosub *searchBestFit//最良一致する領域を検索する
ret=stat
logmes strf("sult:最良一致は%dです。",ret)
}
}
return ret
*searchEmpty//空き領域の要素番号を返す(複数ある場合は最も先頭)
ret=-1
repeat len
if(bflag(cnt)==0){//未割当の場合
ret=cnt
break
}
loop
return ret
*searchFirstFit//十分な大きさを持つ空き領域の要素番号を返す(複数ある場合は最も先頭)
ret=-1
repeat len-start,start
if(bflag(cnt)==0){//未割当の場合
if(isize(cnt)>=p1){//要求サイズ以上の場合
ret=cnt
break
}
}
loop
return ret
*searchLargestEmpty//最も大きな空き領域の要素番号を返す(複数ある場合は最も先頭)
ret=start
max=isize(start)
repeat len-start,start
if(bflag(cnt)==0){//未割当の場合
if(isize(cnt)>max){
ret=cnt
max=isize(cnt)
}
}
loop
return ret
*searchBestFit//十分な大きさを持つ最もサイズの小さい空き領域の要素番号を返す(複数ある場合は最も先頭)
ret=start
min=isize(start)-p1
repeat len-start,start
if(bflag(cnt)==0){//空き領域である
if(isize(cnt)>=p1){
if(isize(cnt)-p1<min){
ret=cnt
min=isize(cnt)-p1
}
}
}
loop
return ret
*expandBufferCnt//領域の数を増やす
sbuf(len-1+BUFEXPANDORDER)="";
bflag(len-1+BUFEXPANDORDER)=0;
isize(len-1+BUFEXPANDORDER)=0;
repeat BUFEXPANDORDER,len
bflag(cnt)=0
memexpand sbuf(cnt),INITBUFSIZE
isize(cnt)=INITBUFSIZE
loop
return
stop
*allocateBuffer//領域を割り当てる。
if(bflag(match)==0){
memexpand sbuf(match),p1 //isizeが正しくない場合に問題が起こらないようにするため、毎回memexpandを実行
bflag(match)=1
if(p1>isize(match)){
isize(match)=p1
}
ret=0
}else{//すでに割り当てられている領域を割り当てようとした
ret=-1
}
return ret
#deffunc free int p1
if(p1){
ret=-1//戻り値
repeat length(sbuf)
if(varptr(sbuf(cnt))==p1){
if(bflag(cnt)==1){
bflag(cnt)=0
ret=0
}else{
ret=-2
}
}
loop
}else{
ret=0
}
return ret
#global
autoinit@HK2mmem
#define NUM 19
dim a,NUM
dim f,NUM
dim p,NUM
dim s,NUM
size=20
repeat NUM
pos 20,cnt*24
button gosub "確保",*lisner
a(cnt)=stat
pos 84,cnt*24
button gosub "解放",*lisner
f(cnt)=stat
loop
pos 0,NUM*24
input size,84,24,10
gosub *show
assert
stop
*show
color 255,255,255:boxf:color
repeat NUM
pos 0,cnt*24+4
mes cnt
pos 148,cnt*24
if(p(cnt)){
i=cnt
repeat NUM
if(cnt!=i){
if(p(cnt)==p(i)){
color 255,0,0
}
}
loop
mes strf("%p,%d",p(cnt),s(cnt))
color 0,0,0
}else{
mes strf("未確保")
}
loop
foreach bflag@HK2mmem
pos 300,cnt*20
mes strf("buf%02d:ptr=%p;flag=%d;size=%d",cnt,varptr(sbuf@HK2mmem(cnt)),bflag@HK2mmem(cnt),isize@HK2mmem(cnt));
loop
return
*lisner
repeat NUM
if(a(cnt)==stat){//確保
if(p(cnt)){
title str(cnt)+":先に解放してください。"
}else{
malloc size
p(cnt)=stat
s(cnt)=size
title str(cnt)+":"+size+"Byte確保しました。"
}
}
if(f(cnt)==stat){//解放
free p(cnt)
title str(cnt)+":freeの戻り値は"+str(stat)+"です。"
p(cnt)=0
}
loop
gosub *show
return