文档库 最新最全的文档下载
当前位置:文档库 › 运行时错误:Stack Overflow的解决办法

运行时错误:Stack Overflow的解决办法

编译正常通过,但运行时出现——

forrtl: severe (170): Program Exception - stack overflow
Image PC Routine Line Source
2DWP.exe 00401A73 Unknown Unknown Unknown
2DWP.exe 004029B9 Unknown Unknown Unknown
2DWP.exe 00449929 Unknown Unknown Unknown
2DWP.exe 0042EDB9 Unknown Unknown Unknown
KERNEL32.dll 77E7CA90 Unknown Unknown Unknown
Incrementally linked image--PC correlation disabled.
Press any key to continue

解决方法:
在project->settings->link->Category=output->stack allocations
设一个足够大的值就行





参考:
https://www.wendangku.net/doc/7118400210.html,/fortran/visual/vfn10/page2.html#Doctor

Issue
2001

https://www.wendangku.net/doc/7118400210.html,/fortran
Doctor Fortran - Don't Blow Your Stack!
Steve Lionel
Visual Fortran Engineering
"Doctor, my stack is overflowing! What does it mean?! Is there a cure?!" The
Doctor frequently sees questions like these, and he realizes it's time for a
general article on the subject of stack allocation, as well as the other
memory allocation types, static and dynamic.

Static allocation
"Everybody's got to be somewhere," the saying goes. And so it is with your
program's data - it has to live somewhere in memory while it is being
referenced (registers are a special kind of memory we won't get into here.)
The compiler, linker and operating system work together to determine exactly
where in memory a piece of data is to reside. The simplest method of
assigning locations is "static allocation", where the data is assigned a
fixed (static) address by the compiler and linker in the executable image
(EXE). For example, if variable X is statically allocated at address 4000,
it is always at address 4000 when that EXE is run, no matter what else is
going on in the system. (DLLs can also have static data - it is allocated at
a fixed offset from the base address where the DLL gets loaded.)

Static allocation is simple from the compiler's perspective because all that
is needed is to create a list of variables that need allocation, and lay
them down in memory one after the other. A run-time advantage of static
allocation is that it is usually easy and fast to access a fixed address and
statically allocated data can be used from anywhere in the program. But
static allocation has disadvantages too. First, if you have any reentrant or
parallel code, the multiple codestreams are both trying to use the same
data, which may not be wanted. Second, if you have many routines which need
a lot of memory just while they're executing, the available address space
can fill up quickly (for example, ten routines each of which declares a
1000x1000 REAL(8) array need a total of 80,000,000 bytes just for those
arrays.) And perhaps most im

portant, with static allocation you must know at
compile-time how much memory you will want.

Up through Fortran 77, the Fortran standard was carefully written in a way
so that static allocation was the only method needed. Even today, static
allocation is the most widely used method - in Visual Fortran, COMMON blocks
and most variables with the SAVE attribute are allocated statically. (Note
that Visual Fortran, by default, implies SAVE for local routine variables
unless it can see that the variable is always written before it is read.)

Dynamic allocation
Dynamic allocation is the complete opposite of static allocation. With
dynamic allocation, the running application must call a system routine to
request a particular amount of memory (for example, 1000 bytes). The system
routine looks to see if that request size is available in the collection
("heap") of memory segments it has available. If the request can be
satisfied, a range of memory addresses is marked as used and the starting
address is returned to the program. If the heap is empty, the operating
system expands the virtual address space of the process to replenish the
heap, stopping only if there is no more virtual memory available. The
program stores the base address in a pointer variable and then can access
the memory. When the program no longer needs the memory, another system
routine is called to "free" it - return it to the heap so that it can be
used again by a future allocate call. You can think of this as similar to
borrowing money from a bank, and then later paying it back (except that
there's no interest!)

The big advantage of dynamic allocation is that the program can decide at
run-time how much memory to get, making it possible to create programs that
can accommodate problems of any size. You are limited only by the total
amount of virtual memory available to your process (a little less than 2GB
in 32-bit Windows) and, as long as you keep your pointers separate, your
allocation is separate from others in the application. However, if your
program "forgets" to free the allocated memory, and no longer has the
pointer through which it is referenced, the allocated memory becomes
unusable until the program exits - a "memory leak". Also, the allocate/free
process can be slow, and accessing data through pointers can itself reduce
run-time performance somewhat.

In Fortran, the ALLOCATE statement performs dynamic allocation, with
DEALLOCATE being the "free" operation. In Visual Fortran, one can use
dynamic allocation in other ways, such as the C-style malloc/free routines,
or by calling Win32 API routines to allocate memory.

Stack Allocation
Stack allocation appears to be the least understood of the three models. The
"stack" is a contiguous section of memory assigned by the linker. The "stack
pointer" is a register (ESP in the X86 architecture) which holds the current
position in the stack. When a prog

ram starts executing, the stack pointer
points to the top of the stack (just above the highest-addressed location in
the stack. As routines are called, the stack pointer is decremented
(subtracted from) to point to a section of the stack that the routine can
use for temporary storage. (The previous value of the stack pointer is
saved.) The routine can call other routines, which in turn create stack
space for themselves by decrementing the stack pointer. When a routine
returns to its caller, it cleans up by simply restoring the saved stack
pointer value.

The stack is an extremely efficient way of creating "scratch space" for a
routine, and the stack plays a prominent role in the mechanism of calling
and passing arguments to routines. Visual Fortran uses the stack to create
space for automatic arrays (local arrays whose size is based on a routine
argument) and for temporary copies of arrays used in array expressions or
when a contiguous copy of an array section must be passed to another
routine. The problem is, however, that the total amount of stack space is
fixed by the linker, and if a routine tries to allocate more space than the
stack can hold, the dreaded "stack overflow" error occurs.

On some other operating systems, OpenVMS for example, the OS can extend the
stack as needed, limited only by the total amount of virtual address space
available. On Windows, however, the stack allocation is determined by the
linker and defaults to a paltry 1MB in the Microsoft linker. You can change
the allocation - for details, see the on-disk documentation topic "Stack,
linker option setting size of" - but this works only for executable images
(EXEs.) If you are building a DLL, it doesn't matter what you set the stack
size to - it is the size specified by the EXE that calls your DLL, (for
example, VB.EXE), which is used.

So, what can you do if changing the stack size is not an option? Reduce your
code's use of the stack. Replace automatic arrays with allocatable arrays
and ALLOCATE them to the desired size at the start of the routine (they will
be automatically deallocated on routine exit unless marked SAVE.) If passing
a noncontiguous array section to another routine, have the called routine
accept it as a deferred-shape array (an explicit interface is required) -
see Chris Bord's article in Newsletter I. Future versions of Visual Fortran
may allocate large temporary values dynamically rather than using the stack,
but for now, being aware of the limits of stack allocation is important.



/STACK 这是CVF 自带的帮助文件上的
Syntax:

/STACK:reserve[,commit]
Sets the size of the stack in bytes.

The reserve argument specifies the total stack allocation in virtual memory.
The default stack size is 1MB. The linker rounds up the specified value to
the nearest 4 bytes.

The optional commit argument is subject to interpretation by the operating
system. In Windows

NT 4 and Windows 2000, it specifies the amount of
physical memory to allocate at a time. Committed virtual memory causes space
to be reserved in the paging file. A higher commit value saves time when the
application needs more stack space but increases the memory requirements and
possibly startup time.

Specify the reserve and commit values in decimal or C-language notation.
(Use the digits 1-9 for decimal values, precede octal values with zero (0),
and precede hexadecimal values with zero and x (0x or 0X).

An alternate way to set the stack is with the STACKSIZE statement in a .DEF
file. STACKSIZE overrides Stack Allocations (/STACK) if you specify both.
You can change the stack after the executable file is built by using the
EDITBIN.EXE tool. For more information, see Editing Files with EDITBIN.

To set these options in the visual development environment, type values in
the Reserve and Commit boxes in the Output category of the Link tab in the
Project Settings dialog box.

相关文档
相关文档 最新文档