2024年1月8日发(作者:)

运行时错误:Stack Overflow的解决办法.txt这世界上除了我谁都没资格陪在你身边。 听着,我允许你喜欢我。除了白头偕老,我们没别的路可选了什么时候想嫁人了就告诉我,我娶你。 现象:

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

forrtl: severe (170): Program Exception - stack overflow

Image PC Routine Line Source

00401A73 Unknown Unknown Unknown

004029B9 Unknown Unknown Unknown

00449929 Unknown Unknown Unknown

0042EDB9 Unknown Unknown Unknown

77E7CA90 Unknown Unknown Unknown

Incrementally linked image--PC correlation disabled.

Press any key to continue

解决方法:

在project->settings->link->Category=output->stack allocations

设一个足够大的值就行

参考:

/fortran/visual/vfn10/#Doctor

Issue

2001

/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 important, 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 program 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, ), 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

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.