Fortran Coder

查看: 19876|回复: 15
打印 上一主题 下一主题

[混编] deallocate内存访问错误及DLL问题

[复制链接]

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
跳转到指定楼层
楼主
发表于 2015-4-16 02:43:30 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
本帖最后由 andy8496 于 2015-4-16 02:47 编辑

又遇到看不见摸不着的问题了!
运行到一个deallocate时,出现图中的错误了。被deallocate的real数组中的数值正常。
可能是什么原因?
这是一个比较大的程序,最近在做一些修改。可以肯定的是,相同位置以前老代码是没有遇到这个问题的。

另一个问题:
当A(main.exe)项目引用B项目(test.dll)时,只要设置A依赖B,不需要在A中添加B相关的文件,就能直接编译通过。但是debug运行时会提示找不着test.dll。
我目前是生成后,将B中的test.dll复制到A的debug文件夹中。还有别的办法吗?

1.jpg (19.82 KB, 下载次数: 421)

1.jpg

2.jpg (15.04 KB, 下载次数: 465)

2.jpg
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
16#
 楼主| 发表于 2015-4-20 18:58:27 | 只看该作者
我用的VS2010+IVF2011。可变长度数组做参数这个好像没有问题。只是用完后释放有问题。同时还有open、write的问题。
已经按照fcode的建议改了代码了。

谢谢大家了!

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

15#
发表于 2015-4-19 21:36:02 | 只看该作者
fcode 发表于 2015-4-17 09:52
这是 F2003 特征,IVF是予以支持的。很早就支持了。这个不存在问题。

但是这个特征需要 interface,如果 ...

查了Gfortran的更新记录,TR 15581从4.2版本就开始支持
stackoverflow上面的解答可能更全面些:
How to pass allocatable arrays to subroutines in Fortran - Stack Overflow
http://stackoverflow.com/questio ... routines-in-fortran

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
14#
 楼主| 发表于 2015-4-18 11:30:40 | 只看该作者
fcode 发表于 2015-4-17 08:25
正如之前我说过的那样,这是具体编译器实现的问题。你要想深究为什么,恐怕只能反汇编分析。

正如 pasuka  ...

只是因为以前的开发习惯不好,用了很多这样的方式:Dll中分配,main.exe中释放,main.exe中open, dll中write,现在都出问题了。之前没用dll,所以好好的。看来只能改代码了。

非常感谢二位的耐心帮助!

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

13#
发表于 2015-4-17 09:52:42 | 只看该作者
pasuka 发表于 2015-4-17 08:55
可分配数组传入子程序后在进行内存分配好像是F08新特性,有可能lz的IVF版本低,所以不支持?!
此外就是D ...

这是 F2003 特征,IVF是予以支持的。很早就支持了。这个不存在问题。

但是这个特征需要 interface,如果不再同一个module里,可能要单独书写 interface

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

12#
发表于 2015-4-17 08:55:44 | 只看该作者
fcode 发表于 2015-4-17 08:25
正如之前我说过的那样,这是具体编译器实现的问题。你要想深究为什么,恐怕只能反汇编分析。

正如 pasuka  ...

可分配数组传入子程序后在进行内存分配好像是F08新特性,有可能lz的IVF版本低,所以不支持?!
此外就是Debug和Release的状态下,IVF编译参数不同导致出现问题

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

11#
发表于 2015-4-17 08:25:01 | 只看该作者
正如之前我说过的那样,这是具体编译器实现的问题。你要想深究为什么,恐怕只能反汇编分析。

正如 pasuka 所言,gfortran 是 OK的,所以不同编译器实现不一样。

同一个编译器,Debug 和 Release 的具体实现也不一样。我不认为研究这个问题有什么意义。

还是那句话:“即便不使用DLL,合理的规范的做法是:谁分配,谁释放”,尤其做大一些的工程时候,这不止是避免程序上出错,也可避免逻辑上出错。而后者非常重要。

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
10#
 楼主| 发表于 2015-4-16 23:52:02 | 只看该作者
真是太奇怪了!
1.上面的代码Debug的时候报错,但是Release的时候就运行正常!!!
2.正常情况下,allocate过的数组是不能再allocate的。但是,test_main.f90这样写居然没有报错:
program main
use test_dll
implicit none
  integer,allocatable :: iv_int(:)
  integer :: iStatus,i
  do i=1,10
    call allocate_test(iv_int,i)
    write(*,*) iv_int
  enddo
  stop
end program
这意思是说:dll中的allocate不关主程序的事?
3.但是这么写又有问题了:
program main
use test_dll
implicit none
  integer,allocatable :: iv_int(:)
  integer :: iStatus,i
  do i=1,10
    call allocate_test(iv_int,i)
    write(*,*) iv_int
  enddo
  allocate(iv_int(8)) ! 到这里报错了,说这是分配过的数组
  stop
end program

4.难道确实是分配了,只是只有dll知道分配到哪儿了,主程序不知道?于是又这么改了下:
Dll加上这么一个函数:
subroutine deallocate_test(iv)
!DEC$ ATTRIBUTES STDCALL,REFERENCE,DLLEXPORT,ALIAS:"deallocate_test"::deallocate_test
implicit none
  integer,allocatable :: iv(:)
  integer :: iStatus
  deallocate(iv,stat=iStatus)
return
end subroutine

主程序这么写:
program main
use test_dll
implicit none
  integer,allocatable :: iv_int(:)
  integer :: iStatus,i
  do i=1,10
    call allocate_test(iv_int,i)
    write(*,*) iv_int
  enddo
  call deallocate_test(iv_int)
  allocate(iv_int(8))
  deallocate(iv_int,stat=iStatus)
  stop
end program

这么就一切正常了。
5.那回到1,Release的时候主程序又是如何知道dll分配的地址,成功的deallocate掉的呢?


哎,真是一团浆糊啊!有没有完美的解决之道啊?

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

9#
发表于 2015-4-16 22:31:35 | 只看该作者
用gfortran编译成dll再调用没发现问题
只是在调用前加了个检查
  if(allocated(iv_int))deallocate(iv_int)
  call allocate_test(iv_int)

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

8#
发表于 2015-4-16 22:13:39 | 只看该作者
1. 在 test_main 里声明可分配数组
2. 调用 test_dll 里的一个函数,获得数组的大小 n
3. 在 test_main 里完成分配。allocate( x(n) )
4. 把 x 传递给 test_dll 里完成计算
5. 在 test_main 里 deallocate

由于可分配数组的内部实现,是编译器的问题(而语法是不干涉具体实现的)。而 DLL 又是windows的事情。
这几者间比较难以协调。

实际上,就算不用 DLL,单纯的 Fortran 工程,我也建议谁定义,谁分配,谁释放。

如果你确实确实要在主程序定义,DLL里分配,主程序释放。那我可能帮不了你。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-5-8 02:39

Powered by Tencent X3.4

© 2013-2024 Tencent

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