2009-03-30 14 views
0

私はDelphiで異なる大規模なデータベースの種類を保存中に問題を抱えています。これにはTItemの配列[1..3500]が含まれています.Titemには2つの配列[1..50]と[1..20]があります。変数をポインタとして設定し、以下のGetMem、FreeMemコマンドを使用しない限り、スタックオーバーフローが発生しますが、それを保存することはできません。コードは以下のとおりです。保存とスタックオーバーフロー

procedure TDatabase.SaveDB; 
var 
TempDB: ^TSaveDB; 
K, X: integer; 
sComment, sTitle, sComposer, sISDN, sCategory: string; 
begin 
GetMem(TempDB, SizeOf(TSaveDB)); 

TempDB.CatCount := fCategoryCount; 
TempDB.ItemCount := fItemCount; 

for K := 1 to fCategoryCount do 
TempDB.Categories[K] := fCategories[K]; 

for K := 1 to fItemCount do 
begin 
    fItems[K].ReturnSet(sTitle, sComposer, sCategory, sISDN, sComment); 
    with TempDB.Items[K] do 
    begin 
    Title := sTitle; 
    Composer := sComposer; 
    Category := sCategory; 
    ISDN := sISDN; 
    end; 

    TempDB.Items[K].Comments[1] := Copy(sComment, 1, 255); 
    Delete(sComment, 1, 255); 
    TempDB.Items[K].Comments[2] := Copy(sComment, 1, 255); 
    Delete(sComment, 1, 255); 
    TempDB.Items[K].Comments[3] := Copy(sComment, 1, 255); 
    Delete(sComment, 1, 255); 
    TempDB.Items[K].Comments[4] := Copy(sComment, 1, 255); 
    Delete(sComment, 1, 255); 

    TempDB.Items[K].KeyWCount := fItems[K].GetKeyCount; 

    for X := 1 to fItems[K].GetKeyCount do 
    TempDB.Items[K].Keywords[X] := fItems[K].GetKeywords(X); 
end; 

AssignFile(DBSave, fSaveName); 
Rewrite(DBSave); 
    Write(DBSave, TempDB); 
Closefile(dBSave); 

FreeMem(TempDB, sizeof(TSaveDB)); 
end; 

答えて

1

問題は「書き込み」ステートメントにあります。任意のポインタを使用すると、あらゆる種類の奇妙な動作が発生します。現在のアプローチの代わりにTFileStreamを使用してこれを書き換えた方が簡単です。

3

使用GetMemかはsetLengthかのTList/TObjectListを、一度にファイル1 TSaveDBに書き込みます。または ファイルの種類を変更し、BlockWriteを使用してすべてを一度に書き込みます。それともTFileStreamを使うのが良いですか?ポインタ、期間を読み書き

NEVER:メイソンの答えに拡大しないように

1

。あなたがプログラムをもう一度実行しているだけでなく、成功の確率が無限小からゼロになるときには、それを実行するのが妥当なものを得るためには大運が必要です。

はむしろ、あなたが読んで、どのようなポインタポイントに記述する必要があります。あなたは「[255]文字列」に「文字列」を作る互換モードで実行している場合を除き長の宣言で指定されていない任意の文字列がポインタであることも

注意、 - このモードでのみ存在しますこれが唯一の文字列だったときに書かれた非常に古いコードとの互換性のためです。

あなたは、固定サイズレコードでゲームをプレイすべき理由はありませんから、単純に全体のことを書いているように見えるので。各フィールドをストリームに書き込んだり、文字列自体を書き込む前に文字列の長さを書き込んだりして、正しく読み込むことができます。ファイルは小さくなり、何も切り詰められません。また

、彼が言うように、tFileStreamを使用しています。古い形式では、ディスク上に残っているレコードのファイルに使用されているので、このような場合に使用する理由はありません。

+0

非常に良い答えです。そこにあるフィールドだけを書き込むだけでファイルサイズが小さくなるだけでなく、データ型のハードコードされた制限の1つに違反するとコードがクラッシュすることもありません。 – mghie

+0

彼はそれをString [255]にコピーしているように見えるので、結果は切り詰めであり、クラッシュではありません。 –

+0

@Loren:fItemCount> High(fItems)の場合、またはfCategoryCount> High(Categories)の場合は、OPコードでどうなるのでしょうか?それはクラッシュするでしょう。 0,1および無限を除いて限界が任意であることに気をつけてください。なぜ3500アイテムしかないのですか?なぜコメントの長さは最大1220ですか? – mghie

関連する問題