Fortran Coder

查看: 3875|回复: 10
打印 上一主题 下一主题

[求助] 新手求助 有关allocate与deallocate之后数组值为undefined

[复制链接]

7

帖子

1

主题

0

精华

入门

F 币
33 元
贡献
15 点
跳转到指定楼层
楼主
发表于 2023-4-12 16:36:17 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
使用oneAPI2021里的INF,visual studio2019 编写Fortran程序
代码大致内容如下:在循环外定义十几个可分配的数组,循环中,对一矩阵的每一列进行操作,根据每列都会生成许多不同大小的数组,因此使用动态数组,使用这些数组进行运算,在循环结尾处都会deallocate。
问题是:在不打断点的调试时,会触发异常如图1,同样的数据同样的代码,运气好能正确地多跑几轮循环(是想要的结果),有时就第一轮直接异常。详细查看后会显示是如图2,调试过近百次,所有的错误最终都是堆已损坏,将近99%的错误发生地点都是allocate和deallocate,debug查看异常点要分配的数组会发现其都是已经被分配了大小,但值都是undefined address如图3;剩下那百分之一的错误是一个动态数组里的值莫名其妙被修改了。

我太菜了,查了好久也没查到所以然,关于undefined address 的描述都很少,我初步猜测是分配和释放时出现了问题导致了错误值。
恳请大佬们答疑解惑,万般感激。

图3 undefined address.png (8.3 KB, 下载次数: 265)

图3 undefined address

图3 undefined address

图2 堆已损坏.png (28.93 KB, 下载次数: 281)

图2 堆已损坏

图2 堆已损坏
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

168

帖子

2

主题

1

精华

大师

Vim

F 币
1021 元
贡献
486 点

规矩勋章

沙发
发表于 2023-4-12 20:07:30 | 只看该作者
可能是传入的C有问题,可以输出size(c)看看是多少

7

帖子

1

主题

0

精华

入门

F 币
33 元
贡献
15 点
板凳
 楼主| 发表于 2023-4-12 20:18:11 | 只看该作者
本帖最后由 noobnobb 于 2023-4-12 20:23 编辑
Transpose 发表于 2023-4-12 20:07
可能是传入的C有问题,可以输出size(c)看看是多少

谢谢你的回复哦,不过这个应该不是C的问题,C的数据如下图。  我在问题描述中只列举了报错中的一个例子,其实是每个allocate和每个deallocate方法都有可能报错,这几条来回报错,不一定是哪个。  


再补充一下,程序是对180*180的矩阵操作,算法需要对每列单独操作,因此循环180列,每次循环都屏幕输出当前循环的结果。运行结果有时第二、三次循环就报错,有时却十几次,最多只能跑到二十多次。


1.png (16.28 KB, 下载次数: 277)

C数组

C数组

168

帖子

2

主题

1

精华

大师

Vim

F 币
1021 元
贡献
486 点

规矩勋章

地板
发表于 2023-4-12 20:22:26 | 只看该作者
没法判断,可能需要源代码

7

帖子

1

主题

0

精华

入门

F 币
33 元
贡献
15 点
5#
 楼主| 发表于 2023-4-12 20:28:39 | 只看该作者
Transpose 发表于 2023-4-12 20:22
没法判断,可能需要源代码

谢谢大佬,不过我写得shit一样,真不想污染大家的眼睛,小小简单算法还三四百行,惭愧啊,我自己再找找,刚才还发现了一些数组的数值不知怎么被改成了极其离谱的数据,想着再从这方面切入去找一找。或者是因为动态数组的隐藏自动分配?   不过既然有的循环能出现正确的结果那说明代码应该没问题,应该是内存或者优化不够的问题吧。

168

帖子

2

主题

1

精华

大师

Vim

F 币
1021 元
贡献
486 点

规矩勋章

6#
发表于 2023-4-12 20:47:08 | 只看该作者
你可以多加一些print看看
另外,可以再用gfortran编译试试 ,两种编译器同时使用,结合起来可能会有效果, 编译的时候加上-fcheck=all

7

帖子

1

主题

0

精华

入门

F 币
33 元
贡献
15 点
7#
 楼主| 发表于 2023-4-13 09:42:42 | 只看该作者
Transpose 发表于 2023-4-12 20:47
你可以多加一些print看看
另外,可以再用gfortran编译试试 ,两种编译器同时使用,结合起来可能会有效果, 编译 ...

好的,感谢大佬提供思路

250

帖子

2

主题

0

精华

宗师

F 币
1731 元
贡献
872 点

规矩勋章

8#
发表于 2023-4-14 12:23:31 | 只看该作者
ALLOCATE和DEALLOCATE增加状态判断试试,比如ALLOCATE(S(100), STAT=sv]) ,然后比较sv是否为0判断是否正常分配数组。

7

帖子

1

主题

0

精华

入门

F 币
33 元
贡献
15 点
9#
 楼主| 发表于 2023-4-14 17:07:50 | 只看该作者
本帖最后由 noobnobb 于 2023-4-14 17:50 编辑
necrohan 发表于 2023-4-14 12:23
ALLOCATE和DEALLOCATE增加状态判断试试,比如ALLOCATE(S(100), STAT=sv]) ,然后比较sv是否为0判断是否正常 ...

感谢大佬的回复,不过实际上发生异常时这条分配/释放语句并没有完全执行,应该是在执行过程中中断了,但有意思的是,在加与不加stat = status这个参数的对比过程中,我发现其在debug界面表现出的结果是不同的,下面附了两张图,分别是在allocate中加入与不加stat参数的运行实例。这也确实印证了您的想法,即这条allocate语句应该是没有正确分配到空间或是中断运行没有正常退出。之后又做了一个小测试,在allocate前将status赋为其他值,发现只要该allocate语句触发异常就不会改变status的值,试过0,-1,2,是在debug的变量页面查看的status值,应该可以判断是异常退出了allocate语句,附上status=2和status=0的图在最下。
再补充一下,上述的问题,目前运行了几十次全部出现在动态一维数组中,轮流出现。


我目前是在往数组越界方面着想,因为我在尝试过其他一些小矩阵(3*3)的例子之后发现仍然有这个allocate问题,只是其成功率会很高,只有很少的几率会出现问题,大概是8:2的比例,试过4个3*3的小矩阵的例子,结果也是想要的结果,因此我认为不可能是内存不够的问题。

请大佬指示!!!

加入status调试.png (76.93 KB, 下载次数: 271)

加入status调试

加入status调试

未加status调试.png (66.33 KB, 下载次数: 276)

未加status调试

未加status调试

status提前设为2.png (37.61 KB, 下载次数: 278)

status提前设为2

status提前设为2

status提前设为0.png (48.14 KB, 下载次数: 273)

status提前设为0

status提前设为0

7

帖子

1

主题

0

精华

入门

F 币
33 元
贡献
15 点
10#
 楼主| 发表于 2023-4-14 17:30:39 | 只看该作者
本帖最后由 noobnobb 于 2023-4-14 17:31 编辑

接上我在一楼所说的,其中有1%的错误是有一个数组值被修改了,变成了很离谱的数,通过不断的输出确定范围,最终是抓到了元凶"call sgemm( )"。是MKL库中的计算矩阵-矩阵乘法的方法,应该是我用它来计算矩阵-一维数组(向量)才导致的问题,可能也是这里导致的数组越界,还是不够严谨
下图是寻找过程

数组值被篡改.png (86.8 KB, 下载次数: 283)

数组值被修改

数组值被修改
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

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

GMT+8, 2024-12-23 22:45

Powered by Tencent X3.4

© 2013-2024 Tencent

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