如果内存真的像堆栈损坏/堆损坏那样损坏。你什么也做不了。程序必然会失败,因为非常底层的信息丢失了。这适用于任何编程语言,甚至 C。
如果损坏的是 Fortran 数组描述符,则无法从 Fortran 中更正它。Fortran 不会向 Fortran 程序员公开这些实现细节。它只能通过ISO_Fortran_binding.h
从 C调用的特殊头文件获得。
如果发生的唯一损坏是让 Fortran 将数组分配到未分配的位置,那么从 C 中恢复它应该相当简单。只需要更改分配内存的地址即可。可分配数组总是连续的。
人们也可以尝试一些肮脏的技巧,比如告诉子例程你传递的是一个指针,而实际上它是一个可分配的指针并将其无效。它可能会在许多实现中起作用。但是以可控的方式取消地址要干净得多。即使它只是您从 Fortran 调用的一个无效 C 函数。
因为您真的只想将地址更改为 0,而不是对数组范围、步幅和其他细节进行任何其他特殊处理,所以即使没有标头也应该很简单。
请注意,描述符仍将包含其他变量中的无意义数据,但这些应该无关紧要。
这是一个快速而肮脏的测试:
Fortran:
dimension A(:,:)
allocatable A
interface
subroutine write_garbage(A) bind(C)
dimension A(:,:)
allocatable A
end subroutine
subroutine c_null_alloc(A) bind(C)
dimension A(:,:)
allocatable A
end subroutine
end interface
call write_garbage(A)
print *, allocated(A)
call c_null_alloc(A)
print *, allocated(A)
end
C:
#include <stdint.h>
void write_garbage(intptr_t* A){
*A = 999;
}
void c_null_alloc(intptr_t* A){
*A = 0;
}
结果:
> gfortran c_allocatables.c c_allocatables.f90
> ./a.out
T
F
ISO_Fortran_binding.h
如果您的编译器提供了正确的版本,则应该使用它。还有implicit none
其他无聊的东西...
我完全不推荐的一个非常肮脏(和非法)的黑客攻击:
dimension A(:,:)
allocatable A
interface
subroutine write_garbage(A) bind(C)
dimension A(:,:)
allocatable A
end subroutine
subroutine null_alloc(A) bind(C)
dimension A(:,:)
allocatable A
end subroutine
end interface
call write_garbage(A)
print *, allocated(A)
call null_alloc(A)
print *, allocated(A)
end
subroutine null_alloc(A) bind(C)
dimension A(:,:)
pointer A
A => null()
end subroutine
> gfortran c_allocatables.c c_allocatables.f90
c_allocatables.f90:27:21:
10 | subroutine null_alloc(A) bind(C)
| 2
......
27 | subroutine null_alloc(A) bind(C)
| 1
Warning: ALLOCATABLE mismatch in argument 'a' between (1) and (2)
> ./a.out
T
F