保存和堆栈溢出
Posted
技术标签:
【中文标题】保存和堆栈溢出【英文标题】:Saving and Stack Overflows 【发布时间】:2009-03-30 16:34:23 【问题描述】:我在 Delphi 中保存各种大型数据库类型时遇到问题。它包含一个 TItem 的数组 [1..3500],而 TItem 又包含两个数组 [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】:使用 GetMem 或 SetLength 或 TList/TObjectList 并一次将一个 TSaveDB 写入文件。或者 更改文件类型并使用 BlockWrite 一次将其全部写入。甚至更好:使用 TFileStream。
【讨论】:
【参考方案2】:您的问题出在“写”语句中。用任意指针做事会导致各种奇怪的行为。如果你使用 TFileStream 而不是当前的方法重写它,你会容易得多。
【讨论】:
【参考方案3】:扩展梅森的答案:
从不读取或写入指针,句点。要从中获得任何合理的结果需要很大的运气,而在现实世界中,当您不只是再次运行程序时,成功的几率会从无穷小变为零。
相反,您需要读取和写入指针指向的内容。
另外请注意,任何长度未在声明中命名的字符串都是指针,除非您在兼容模式下运行,将“string”转换为“string[255]”——此模式仅适用于与我们仅有的字符串时编写的非常古老的代码兼容。
由于您似乎只是将整个内容写出来,因此没有理由玩具有固定大小记录的游戏。只需将每个字段写入流,在写入字符串本身之前写入字符串的长度,以便您可以正确加载它。文件会更小,不会被截断。
另外,正如他所说,使用 tFileStream。旧格式用于保留在磁盘上的记录文件,在这种情况下没有理由使用它。
【讨论】:
很好的答案。只写入尽可能多的字段不仅会减小文件大小,而且还会防止代码在违反数据类型中的硬编码限制之一时崩溃。 他似乎正在将其复制到 String[255],因此结果是截断,而不是崩溃。 @Loren:这不是我的意思——如果 fItemCount > High(fItems) 或 fCategoryCount > High(Categories),OP 代码中会发生什么?它会崩溃。没关系,除了 0、1 和无穷大之外的限制是任意的。为什么只有 3500 项?为什么最大评论长度是 1220? 3500 限制是在程序范围内施加的,它不会在保存例程中被破坏。评论将剪辑到 1220,但不会崩溃。 我的意思是 1) 从发布的代码中看不出总是遵守限制,并且 2) 任何任意限制(不遵循技术限制)都是不好的。以上是关于保存和堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章