24小时热门版块排行榜    

CyRhmU.jpeg
查看: 1945  |  回复: 9
当前主题已经存档。

jhuiuc

至尊木虫 (正式写手)

[交流] 【求助】Fortran里面Stack Overflow【已完成】

Visual Fortran, 程序里面定义了一个整型数组 JS(N), 所有A-H, O-Z参数和数组定义为Real*8类型. 这个数组在Call语句被用到, Call Sub1(A, B, JS).

当N取352以下时, 程序完全正常, 再大就会出现severe 170 -Stack Overflow 的错误信息(Debug时指向这个JS(N)数组).
severe(170): Program Exception - stack overflow
FOR$IOS_PGM_STKOVF. The Compaq Fortran RTL has detected a stack overflow while executing your program. See your Release Notes for information on how to increase stack size.

1. 如何查这个Release Notes?
2. 如何增加Stack Size?
3. 欢迎其他任何相关评论. 如果需要我补充其它信息, 请指出.

程序大概结构是(本身没有任何语言问题, 就是修改N值的时候会出现Overflow现象):
Program Main
Implicit real*8 (A-H, O-Z)
Parameter (N=300)
Integer JS(N)
Real*8 A1(N, N), B1(N,N),X1(N)
......
......
CALL Sub1(A1,B1,N,X1,LL,JS) (A1,B1是2维数组, X1是1维数组, LL是整型数)
......
......
END

SUBROUTINE Sub1(A1,B1,N,X1,LL,JS)
......
......
Return
End

[ Last edited by wangen994 on 2010-1-18 at 12:05 ]
回复此楼
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

magic7004

金虫 (职业作家)

★ ★ ★ ★ ★ ★ ★
余泽成(金币+2,VIP+0):辛苦了! 1-16 16:40
jhuiuc(金币+5,VIP+0):我刚刚修改了原帖,可否给出一些具体意见,另外到底什么是Stack和heap? 谢谢 1-15 20:46
一般默认的stack size是足够的,通常stack overflow 都是某些bug或者很恶劣的算法导致的。
建议搂住修改一下代码,减小stack的使用。比如避免递归调用,避免把很大的结构放在stack里等。建议搂住把大的结构或者数组放在heap里,把递归改成循环。

ps:stack的大小通常是通过调整编译器的参数修改的,这个去找编译器的文档吧。
流氓不可怕,可怕的是流氓有文化,有文化又BH的流氓无敌~~!
2楼2010-01-16 16:38:09
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

magic7004

金虫 (职业作家)

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
jhuiuc(金币+10,VIP+0):有可能是在调用子程序Sub1的时候,里面参数都是很大数组, 导致Stack Overflow, 可否解释到底什么是Stack和Heap 1-15 20:51
jhuiuc(金币+5,VIP+0): 1-15 20:52
jhuiuc(金币+10,VIP+0):虽然我写过很多Fortran,但还不知道什么是Heap,能给个例句吗?C语言的也可以 1-16 19:09
貌似楼主有两个N X N维的数组,如果这个是放在stack里的话,那就是非常大的了。
我不清楚FORTRAN的语法,不知道楼主声明数组的方式是不是会把数组放在stack里。
如果是放在stack里的话,建议搂住把数组放到Heap里。

ps:stack就是堆栈,Heap就是堆。每个线程都有自己的stack用来保存局部变量和函数调用信息,根据编译器不同,通常大小1~4MB之间,如果用完了就会出现stack overflow exception。
如果楼主不清楚的话,建议看一下Fortran语法关于内存管理的部分,非常大的数组应该是动态管理的,放在heap里。。

[ Last edited by magic7004 on 2010-1-16 at 16:50 ]
流氓不可怕,可怕的是流氓有文化,有文化又BH的流氓无敌~~!
3楼2010-01-16 16:47:07
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

maomao1210

金虫 (正式写手)

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...
余泽成(金币+2,VIP+0):辛苦了! 1-16 23:13
jhuiuc(金币+88,VIP+0):可否解释一下增加Stack Size对程序会产生什么影响, 比如运行速度降低? 1-16 10:17
引用回帖:
Originally posted by jhuiuc at 2010-1-16 16:25:
Visual Fortran, 程序里面定义了一个整型数组 JS(N), 所有A-H, O-Z参数和数组定义为Real*8类型. 这个数组在Call语句被用到, Call Sub1(A, B, JS).

当N取352以下时, 程序完全正常, 再大就会出现severe 170 -Sta ...

这样修改:stack size
是我从我们群里截的图。答案是某个大侠给出来的。可以参考一下。

[ Last edited by maomao1210 on 2010-1-16 at 19:41 ]
4楼2010-01-16 16:58:39
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

hakekill

木虫 (小有名气)

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
余泽成(金币+1,VIP+0):谢谢参与应助! 1-16 23:13
jhuiuc(金币+10,VIP+0):谢谢讨论! 1-16 10:15
这个问题好像有人问过了,我还是推荐使用动态分配数组来做,省心省事
5楼2010-01-16 21:45:38
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

maomao1210

金虫 (正式写手)

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
jhuiuc(金币+20,VIP+0):内存1G,看来问题就在Call语句里面的数组太大了,我本来想换成common,太麻烦 1-16 19:07
余泽成(金币+2,VIP+0):辛苦了! 1-17 21:40
引用回帖:
Originally posted by jhuiuc at 2010-1-16 16:25:
Visual Fortran, 程序里面定义了一个整型数组 JS(N), 所有A-H, O-Z参数和数组定义为Real*8类型. 这个数组在Call语句被用到, Call Sub1(A, B, JS).

当N取352以下时, 程序完全正常, 再大就会出现severe 170 -Sta ...

你好,栈空间是用来存放局部变量,参数地址的内存区域,如果你内存足够大,一般不会有什么问题。
像你程序中出现的问题,如果不重新革新代码的话,就两种方法可以选择,第一就是增大栈空间大小,其次就是该为使用堆(heap),也就是 hakekill 虫子说的,动态分配数组大小。 既然你设为100M可以运行的话,一般不会有问题的。我不知道你机器内存多大。

[ Last edited by maomao1210 on 2010-1-17 at 14:56 ]
6楼2010-01-17 14:54:49
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

maomao1210

金虫 (正式写手)

★ ★ ★ ★ ★ ★ ★ ★ ★ ★
jhuiuc(金币+10,VIP+0):就这样用吧,暂时还没什么问题,改的话要动大手术 1-16 19:08
引用回帖:
Originally posted by magic7004 at 2010-1-16 16:38:
一般默认的stack size是足够的,通常stack overflow 都是某些bug或者很恶劣的算法导致的。
建议搂住修改一下代码,减小stack的使用。比如避免递归调用,避免把很大的结构放在stack里等。建议搂住把大的结构或者数 ...

强烈建议楼主采纳magic7004 的建议,把代码重新革新一下,呵呵。
7楼2010-01-17 14:57:54
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

magic7004

金虫 (职业作家)

★ ★
余泽成(金币+2,VIP+0):辛苦了! 1-17 21:40
引用回帖:
jhuiuc(金币+10,VIP+0):虽然我写过很多Fortran,但还不知道什么是Heap,能给个例句吗?C语言的也可以 1-16 19:09

C++的例子吧
int a[100];
这个数组a就是放在stack里的,会占用400字节的栈空间。
int* b = new int[100];
这个数组b就是放在堆里的,它会占用4个字节的栈空间和400字节的堆空间。
所以如果 int a[300][300];
就会占用300*300*4 = 360k的栈空间,如果的栈默认大小是1M,那么程序理有几个这样的数组就很容易造成stack overflow.
所以上面程序要改成
typedef int p[300];
p* a = new p[300];
这样的话就只会占用4个字节的栈空间,其余的数据在堆里。而堆空间是没有大小限制的,理论上可以分配到2G的用户内存空间(32位Windows的默认配置)被用完为止。

[ Last edited by magic7004 on 2010-1-18 at 11:50 ]
流氓不可怕,可怕的是流氓有文化,有文化又BH的流氓无敌~~!
8楼2010-01-17 21:36:55
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

tomato12345`

金虫 (小有名气)

★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖交流
nono2009(金币+2):谢谢交流! 2010-02-04 09:24
Integer JS(N)
Real*8 A1(N, N), B1(N,N),X1(N)
是在stack中分配内存,如果stack size太小则内存溢出,可参照论坛帖子增大stack size,对于大的数组最好采用堆内存分配,在fortran中可用:

real (kind=8), allocatable:: A1(N, N), B1(N,N),X1(N) !定义数组为动态内存分配

allocate(A1(N, N),) 在堆上动态分配内存


,程序结束后A1将自动释放堆内存空间,但最好自己释放已经分配的内存deallocate(A1)
9楼2010-02-04 09:05:47
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

senlia

木虫 (小有名气)

★ ★
小木虫(金币+0.5):给个红包,谢谢回帖交流
jjdg(金币+1):辛苦了! 2010-02-09 19:36
子程序传递的参数所需空间不是很大时 4楼的方法满好的 不用把数组改为动态定义[这个工作满烦的]
如果特别大 那就治标不治本了 那就还是用动态定义吧
好像用公共变量定义可以解决这个问题吧 只是公共变量不大好管理 要很小心才行

[ Last edited by senlia on 2010-2-9 at 19:31 ]
书到用时方恨少, 天涯何处无芳草.
10楼2010-02-09 19:28:06
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 jhuiuc 的主题更新
普通表情 高级回复(可上传附件)
信息提示
请填处理意见