Delphi 字节长为1MB的缓冲区存在问题

Delphi 字节长为1MB的缓冲区存在问题,delphi,file,memory-management,Delphi,File,Memory Management,因为我可以解决这个问题:我想使用1 MB或更多字节的缓冲区,而使用数组则不可能,因为我有一个堆栈流。我曾经考虑过getmem和freemem,或者使用tmemorystream,但并没有准确地理解它。对我来说,需要使用一个缓冲区来使用具有读/写功能的tfilestream复制文件。 我不想在内存中一次加载所有的数据,也不想在磁盘中写入所有的数据;对于它,我已经找到了解决方案,但并不需要它。 非常感谢。Daniela.如果堆栈溢出,则变量不适合堆栈。很明显,您使用的是局部变量 通过使用堆来解决问题

因为我可以解决这个问题:我想使用1 MB或更多字节的缓冲区,而使用数组则不可能,因为我有一个堆栈流。我曾经考虑过getmem和freemem,或者使用tmemorystream,但并没有准确地理解它。对我来说,需要使用一个缓冲区来使用具有读/写功能的tfilestream复制文件。 我不想在内存中一次加载所有的数据,也不想在磁盘中写入所有的数据;对于它,我已经找到了解决方案,但并不需要它。
非常感谢。Daniela.

如果堆栈溢出,则变量不适合堆栈。很明显,您使用的是局部变量


通过使用堆来解决问题。GetMem或SetLength。

一个简单的解决方案是使用动态数组。它们的数据分配在堆上,因此可以避免堆栈溢出。与直接使用内存分配函数相比,它们的优点是它们被重新计数,并且一旦最后一个引用超出范围,它们分配的内存将自动释放

var buffer:array of byte;
begin
  SetLength(buffer,100000);
  ...
  //Will be freed here as buffer goes out of scope
end;

缓冲区变量是在堆栈上分配的,Delphi编译器使用的默认最大堆栈大小是1 MiB。因此,解决方案是使用项目选项或以下全局指令设置更高的限制:

{$MAXSTACKSIZE 4194304} // eg. now maximum is 4 MiB 
另一种方法是使用堆而不是堆栈,任何动态分配的内存,在您的情况下,最好的解决方案可能是动态数组


性能说明:堆栈比堆快

使用内存函数而不是数组是一个糟糕的策略,因为你会遇到很多错误。试着理解为什么会出现堆栈溢出。你可能在一个循环或递归函数中,问题更像是你在循环中犯了一个编程错误。实际上,他的问题是数组分配。它与递归无关。1 MB是正常的堆栈大小,因此如果他想使用如此大的内存块,他必须移动到堆中。@az0典型堆栈的总大小是1 MB。我想你可以告诉链接器更改它,但这不是正确的做法。因此,在堆栈上分配1MB阵列是错误的,这就是OPs问题。在堆上分配大数据是正确的。@az01您似乎认为可以在堆上分配任何大小的数据结构。这显然是错误的。@az01:堆栈溢出通常发生在循环中或通过递归发生,这是对的。但是在这个特殊的例子中,Danny只是通过分配一个非常大的数据结构来吸收他的整个堆栈框架。即使没有循环或递归,试图获取超过1MB的堆栈内存也是注定要失败的。增加堆栈大小会带来危险。应用程序中的每个线程都需要保留该虚拟内存。把它往上撞会给地址空间带来压力。堆是处理大数据块的方法。@David Heffernan,堆栈在32位Windows中很便宜,所以这些危险不是需要担心的实际问题。在多核机器上就没有那么便宜了。4gb地址空间可以很快被64路机器和4mb堆栈占用,比如,-1。增加堆栈绝对不是正确的解决方案。对于堆栈大小,大多数对CreateThread的调用都会传递0,这会导致进程默认值,您刚刚将其更改为4MB。通常你无法控制应用程序中的所有线程。