Fortran Coder

查看: 1422|回复: 13

[调试器] Debug才有的问题

[复制链接]

86

帖子

22

主题

0

精华

大师

F 币
1199 元
贡献
631 点
发表于 2015-9-9 00:33:34 | 显示全部楼层 |阅读模式
遇到一个问题:Debug模式的时候,运行到一个奇怪的问题,运行到一个subroutine的end subroutine的时候,就弹出了附件中中的窗口,这时候查看输出参数的值,已经有了我想要的结果。Release的时候就不会有这个问题。
何解?
000000000.png
回复

使用道具 举报

615

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
326 元
贡献
102 点

新人勋章爱心勋章水王勋章元老勋章

发表于 2015-9-9 08:34:44 | 显示全部楼层
看黑框的错误提示

86

帖子

22

主题

0

精华

大师

F 币
1199 元
贡献
631 点
 楼主| 发表于 2015-9-9 10:58:02 | 显示全部楼层
黑框提示
program exception—Access violation

然后给了几个调用的位置,最初的位置就是出问题的subroutine的end subroutine处,其他的按照调用的“后、先”顺序给的调用处的位置。

奇怪的地方是,逐步运行一直是到这个子程序运行完毕,得到正确结果后,到end subroutine的时候才出错的。检查过多遍,没有“未分配的数组传递到函数中,函数中也未分配就直接使用”的问题,不然也出不了结果。
我猜测问题应该来自可变长度数组和指针的分配。
可疑点一:可变长度数组。在这个subroutine中循环调用了一个来自DLL的子程序,这个被调用的子程序有一个输出参数是可变长度数组,这个数组在被调用子程序内部分配,获取的值供调用子程序使用。
调用子程序用完后没有释放,因为释放会出问题。(之前群主说过这是一个不好的做法,不遵循“谁分配谁释放”,但是我当前的工作这么处理会方便很多,切不释放就不会有问题,各处就一直还是这么用的)。
窃以为问题由此疑点导致的可能性较低。
可疑点二:这个subroutine中用了指针,但是我一直也是这么用的,也没出过问题,大概是这么个过程:
  type(pl), pointer :: pP,hP
......
  allocate( hP )
  pP=>hP
  nullify(hP%next)
  
    do j=1,icount
      pP%i= iarray(j)
      allocate( pP%next )
      pP=>pP%next
    enddo

  pP=>hP
  do i=1,icount
    iarray1(i) = pP%i
    if ( .not. associated(pP%next) ) exit
    pP=>pP%next
  enddo

  pP=>hP
  do i=1,icount+1
    deallocate(pP)
  enddo

还请再给把把脉啊!

615

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
326 元
贡献
102 点

新人勋章爱心勋章水王勋章元老勋章

发表于 2015-9-9 12:10:51 | 显示全部楼层
在子程序结束处出错,极大可能是堆栈失衡。
可以考虑 DLL 的调用是否合理?调用协定是否一致?DLL 和 exe 是否都是 Fortran 书写?

非常建议你:谁分配谁释放。这非常重要。尤其是较大的程序。

86

帖子

22

主题

0

精华

大师

F 币
1199 元
贡献
631 点
 楼主| 发表于 2015-9-9 14:07:30 | 显示全部楼层
都是fortran写的,调用应该也没有问题,因为被调用的子程序在别的子程序中也是这么调用的。
刚百度了下这个堆栈失衡,确有可能(①Release没问题②程序尾)。没有“谁分配谁释放”会导致堆栈失衡吗?

我也想“谁分配谁释放”。但是有时候感觉很不方便。比如,要读取一个文件,实现也不知道里面有多少数据,只能给“派”去读文件的子程序一个虚数组,在这个子程序读的时候在他内部分配。如果要把这个此程序放到DLL中,就不能“谁分配谁释放了”。在么就是先读一遍,统计下数据量,然后分配,然后读一遍。但是对于结构复杂,要进行比较复杂解析的文件,效率就下去了。

如果是堆栈失衡,除了"谁分配谁释放",还有别的招吗?

顺便再问个问题,我上面那种指针用完了释放改如何操作?

86

帖子

22

主题

0

精华

大师

F 币
1199 元
贡献
631 点
 楼主| 发表于 2015-9-9 14:15:29 | 显示全部楼层
本帖最后由 andy8496 于 2015-9-9 14:37 编辑

刚异想天开想的想法:
Fortran有没有类似C++的内联函数?或者有没有什么编译选项能实现“内联”的效果?
这样在编译的时候,直接吧被调用的内联函数复制到调用函数中,我在调用函数中释放,是不是没问题了?

86

帖子

22

主题

0

精华

大师

F 币
1199 元
贡献
631 点
 楼主| 发表于 2015-9-9 14:36:02 | 显示全部楼层
“重试”,继续运行,程序就走到这儿了:
11.jpg
22.jpg

615

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
326 元
贡献
102 点

新人勋章爱心勋章水王勋章元老勋章

发表于 2015-9-9 14:50:29 | 显示全部楼层
怎么会效率下去呢?
1.先获得大小
2.返回,分配
3.再读取
和直接调用,也一样要获得大小,分配,再读取呀。
不过是分两个过程而已,实际要做的事情是一样的。所以没有太大的差别的。

最好是严格执行“谁分配谁释放”

语法是没有考虑DLL的问题的,我不确定编译器能不能在DLL里处理好语法中所有的标准。至少 newunit 这种都处理不好。

86

帖子

22

主题

0

精华

大师

F 币
1199 元
贡献
631 点
 楼主| 发表于 2015-9-9 15:33:50 | 显示全部楼层
比如,一个文件中有十几种对象,这些对象的个数都不知道。读取的时候,如果要先获取这些对象的数量,就要先把文件逐行读取、解析一遍,获取各个对象的数量,然后分配好,然后再读取、解析一遍,获取各个对象的参数,这个,应该没有用上指针,一次读取、解析完效率高吧?
其实吧,也不会有太大影响。数据量比较大,后面的编码一定要这么干了。前面的要不要改我再权衡下吧!谢谢了!

还有就是上面问到的问题,这么用指针:
  type(pl), pointer :: pP,hP
......
  allocate( hP )
  pP=>hP
  nullify(hP%next)
  
    do j=1,icount
      pP%i= iarray(j)
      allocate( pP%next )
      pP=>pP%next
    enddo

  pP=>hP
  do i=1,icount
    iarray1(i) = pP%i
    if ( .not. associated(pP%next) ) exit
    pP=>pP%next
  enddo
完了我该怎么释放啊?以及一些子程序中间的不定长度数组,在退出子程序的时候要不要deallocate?

615

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
326 元
贡献
102 点

新人勋章爱心勋章水王勋章元老勋章

发表于 2015-9-9 17:17:10 | 显示全部楼层
单向串表,一般用递归函数释放。
双向串表就简单一些。

子程序里的可分配数组,无需释放(退出子程序时会自动释放)
但子程序里分配的指针,必须释放,否则会内存泄露。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

QQ|捐赠本站|Archiver|关于我们 About Us|群聊|Fcode

GMT+8, 2019-10-17 03:06

Powered by Discuz! X3.2

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表