- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在访问 C 数组时遇到段错误,该数组在下面的 Fortran 文件中分配。有一些调试问题,例如文件写入没有写入任何有意义的内容,并且我初始化了一个我从未使用过的变量 i
。
但是,我发现了以下内容:
i
(但仍声明它):无段错误HESS
(不是 HESS_COPY
):无段错误i
:segfault有谁知道什么可能会导致这种行为?段错误本身发生在 ARRAY_PTR = C_LOC(HESS_COPY(1, 1))
行。我正在使用带有调试标志的 gfortran
和 gcc
进行编译(无优化)。
valgrind
表示存在无效写入(最上面的两个文件是我在下面显示的文件):
Invalid write of size 8
at 0xBEEA3E: get_pointer (modsparsehess.f90:34)
by 0xA75D7A: print_hess (sparse_hessian_c.c:108)
by 0x866C95: quench_ (quench.f:316)
by 0x7F2DBE: mc_ (mc.F:368)
by 0x4B65E2: mcruns_ (mcruns.f:62)
by 0x459245: MAIN__ (main.F:430)
by 0x45A33F: main (main.F:21)
Address 0x87 is not stack'd, malloc'd or (recently) free'd
C 文件
#include <stdio.h>
void get_pointer(double ** hessian);
void print_hess(int *arr_size) {
// Create a pointer to handle the hessian
double **hessian;
int i;
i = 0;
get_pointer(hessian);
printf("%8.3f", **hessian);
// Open a file for writing
FILE *fptr = fopen("hessian_out", "w");
// Print the hessian
fprintf(fptr, "\n");
fclose(fptr);
}
Fortran 文件
MODULE MODSPARSEHESS
USE, INTRINSIC :: ISO_C_BINDING
USE MODHESS, ONLY: HESS
INTERFACE
SUBROUTINE PRINT_HESSIAN(DIMENSIONS) BIND(C, NAME='print_hess')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: DIMENSIONS
END SUBROUTINE PRINT_HESSIAN
END INTERFACE
CONTAINS
SUBROUTINE GET_POINTER_IN_C(ARRAY_PTR) BIND(C, NAME='get_pointer')
! C signature: void get_pointer(double ** hessian);
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
! Arguments
TYPE(C_PTR), INTENT(OUT) :: ARRAY_PTR
! Local variables
REAL(C_DOUBLE), DIMENSION(:,:), &
ALLOCATABLE, TARGET :: HESS_COPY
! Copy the hessian into HESS_COPY
IF (.NOT. ALLOCATED(HESS_COPY)) THEN
ALLOCATE(HESS_COPY(SIZE(HESS, 1), SIZE(HESS, 2)))
END IF
HESS_COPY(:, :) = HESS(:, :)
! Now get the pointer
ARRAY_PTR = C_LOC(HESS_COPY(1, 1))
END SUBROUTINE GET_POINTER_IN_C
END MODULE MODSPARSEHESS
最佳答案
变量HESS_COPY
是Fortran过程GET_POINTER_IN_C
的本地、未保存、可分配的变量。
因此,每当过程开始执行时,它总是未分配的。因此,在该过程的第一个可执行语句中测试其分配状态是多余的。
因此,在过程执行结束时,未保存的局部变量也会自动释放。因此,在过程结束时的 C_LOC 引用获得了即将停止存在的对象的地址。
然后,C 代码使用不存在的对象的地址,并且程序失败。
如果HESS_COPY
变量保存在本地或保存的模块变量中,它将在过程调用之间继续存在。
(自 Fortran 2008 起,所有模块变量均已保存,以前的语言修订版正式要求,如果模块未在事件作用域中持续引用,则对相关模块变量进行显式指定的 SAVE。)
(顺便说一句,从 Fortran 2003 开始,该语言的规则也意味着分配测试、分配语句和后续赋值可以简单地替换为单个语句 HESS_COPY = HESS
.)
此外,在 C 代码中,正在尝试返回不存在的指针中的信息。在原始代码中,hessian 被声明为指向指向双重的指针的指针 - 请注意两个间接级别。如果没有某种初始化,第一级间接寻址将“随机”指向内存中,然后 Fortran 代码将尝试将其结果存储在该随机位置。
作为替代方案,请考虑:
#include <stdio.h>
void get_pointer(double ** hessian);
void print_hess(int *arr_size) {
// A pointer to double (one level of indirection).
double *hessian;
// Pass the address of that pointer.
get_pointer(&hessian);
// print the value of the double being pointed at.
printf("%8.3f\n", *hessian);
// print the value of the next double in the array
// (assuming that there is more than one).
printf("%8.3f\n", *(hessian+1));
// (or equivalently, `hessian[1]`)
}
Vladimir F 在注释中提到的 Fortran 指针方法需要两个 Fortran 过程 - 一个类似于分配 Fortran 指针并复制数据的过程,第二个则取消分配该指针。对分配过程的每次调用都需要与对释放过程的相应调用相匹配,并传递相同的指针。大致如下:
SUBROUTINE GET_POINTER(ARRAY_PTR) BIND(C, NAME='get_pointer')
! C signature: void get_pointer(double **);
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_LOC, C_PTR, C_DOUBLE
TYPE(C_PTR), INTENT(OUT) :: ARRAY_PTR
REAL(C_DOUBLE), POINTER :: HESS_COPY(:,:)
! See also the SOURCE= specifier.
ALLOCATE(HESS_COPY(SIZE(HESS,1), SIZE(HESS,2))
HESS_COPY = HESS
ARRAY_PTR = C_LOC(HESS_COPY)
END SUBROUTINE GET_POINTER
SUBROUTINE RELEASE_POINTER(ARRAY_PTR) BIND(C, NAME='release_pointer')
! C signature: void release_pointer(double*);
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER, C_DOUBLE
TYPE(C_PTR), INTENT(IN), VALUE :: ARRAY_PTR
REAL(C_DOUBLE), POINTER :: HESS_COPY(:,:)
CALL C_F_POINTER(ARRAY_PTR, HESS_COPY, SHAPE(HESS))
DEALLOCATE(HESS_COPY)
END SUBROUTINE RELEASE_POINTER
关于c - 将分配的 C_PTR 到 Fortran 数组传递给 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28351919/
是的,我知道..,这不是想象的...这是一个真正的 Fortran 问题。 以前的版本是指 Fortran 2003、95、90,甚至 77。 我所说的“向后兼容”是指可以轻松运行为 2008 年以前
我有一个程序,它的变量中有一个值。一旦确定了该值,我想调用另一个程序并使用该变量的值来确定在新程序中的位置。有人知道该怎么做吗? 最佳答案 如果您有 Fortran 2008 编译器,您将拥有标准子例
namelist 是一种有用的 fortran 结构,可以从文件中快速初始化变量。 namelist 有一个名称并包含一组具有已知类型的变量。这使得它类似于 type 结构。 通常情况下,给程序或子例
我正在遍历索引,我正在检查我是否不在第一个循环交互和另一个条件中。如果第一个条件是 .False.,我不想评估第二个条件。 do i = 1, n if ( i /= 1 .and. var(
Fortran 2003 具有用于数组连接的方括号语法,Intel fortran 编译器也支持它。我在这里为矩阵连接写了一个简单的代码: program matrix implicit none r
我正在尝试通过重载类型名称来制作自定义数据类型构造函数。但是,在进行调用时,将调用默认构造函数。我不明白我做错了什么。 这是有问题的代码片段。 module test type, pu
我的最终目标是在 Fortran 中有一个通用的映射函数,即一个接受任意类型 A 的数组和一个 A->B 类型的函数的函数,将此函数应用于给定数组的所有元素并返回一个B 类型的数组。我无法用数组实现它
我正在学习 Fortran,在使用格式编写时发现了一些奇怪的东西(我使用的是 Fortran onlinegdb) Program Hello real, dimension(3,2):: array
Fortran 中的INTERFACE 语句是否使其成为正式实现multiple dispatch 的编程语言? ? (我问是因为所链接的维基百科文章在其看似全面的支持相关范式的示例编程语言列表中并未
我可以使用 Fortran 95 编译器编译 Fortran 90 文件吗? Fortran 95 似乎有很多,但 Fortran 90 没有。 最佳答案 这个可以: NAGWare f95 Comp
嗨,我在 Fortran 中对二维离散化问题强加边界条件时遇到了麻烦。我的离散化网格是一个二维正方形,在 x,y 方向上从 -L 到 L。 我想强加这样的边界条件, 在 x=L 的边界线上,指定了函数
Fortran 是否有与 C assert 等效的标准函数/关键字? ? 我找不到 assert我在Fortran2003标准中提到过。我发现了一些如何使用预处理器的方法,但是在这个 answer建议
我有一系列的作业,使用“;”将它们分配给同一个ike。分开statemnts,但我收到此错误: 1.0;磅(1,9) 1个 错误:(1)处无法分类的陈述 在文件LJ.F90:223中 如果每个语句都在
我正在使用 gfortran -std=f2008。我有一个函数,它返回一个包含可分配数组的派生类型。该函数在返回之前调用allocate()。似乎在分配数组的函数返回之后,数组会自动释放一段时间,并
我制作了这个小型测试程序来“证明”在编译之前(或者如果你让它们可分配),你不能在不指定它们的大小的情况下使用向量。我的观点失败了。我期待本地向量“num”会失败。程序在执行程序之前无法知道它的大小。大
出于优化原因,Fortran 强制子例程或函数的虚拟参数不是别名,即它们不指向相同的内存位置。 我想知道相同的约束是否适用于函数的返回值。 换句话说,对于给定的 myfunc 函数: function
我已经在Fortran 90中编写了一个相当大的程序。它已经运行了一段时间了,但是今天我尝试将其提高一个档次并增加问题的大小(这是研究非标准的有限元求解器,如果那样的话)。可以帮助任何人...)现在,
在 C 和 C++ 中,有许多操作会导致未定义的行为,即允许编译器做任何它想做的事情的情况。 Examples包括在释放变量后使用它,释放变量两次和取消引用空指针。 Fortran 是否也有未定义的行
通常我使用fortran进行数值分析,然后使用matlab、R和python进行后期和前期工作。 我发现 matlab、R 和 python 在终端中提供了命令提示符,以便您可以运行脚本以及从命令行立
在 Fortran 中将变量设置为 +Infinity 的最安全方法是什么?目前我正在使用: program test implicit none print *,infinity() con
我是一名优秀的程序员,十分优秀!