我有一个简单的程序,它使用新的 Fortran 2018 语义结合了 C++ 和 Fortran。我的示例基于https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/697150中评论 #12 中提供的内容。我的示例使用英特尔编译器(2019 update5)运行良好,但是当我使用检查指针标志时,一旦我调用 Fortran 子例程,它就会因段错误而崩溃。使用 gfortran (9.2.0),程序正确执行,但退出时出现堆栈粉碎错误。
C++
#include <iostream>
#include <vector>
#include <ISO_Fortran_binding.h>
extern "C"
{
void dummy_subroutine(int , int , double *, int *, CFI_cdesc_t *, int *);
}
int main()
{
std::cout << "Hello, World from c++!" << std::endl;
// Send and recv data from fortran
int array_size = 10;
std::vector<double> dbl_array_tosend(static_cast<size_t>(array_size), -1.5);
std::vector<int> int_array_tosend(static_cast<size_t>(array_size), 3);
double *dbl_to_recv = 0; // We want fortran to allocate new array here
CFI_cdesc_t *pointer_to_recv = 0; // Pointer to pass to fortran
CFI_CDESC_T(1) c_desc; // Macro to create C descriptor, 1 is the rank
CFI_rank_t rank = 1; // We want fortran to allocate a rank 1 array
// Set the pointer to C descriptor address
pointer_to_recv = (CFI_cdesc_t *)&c_desc;
// Establishes a C descriptor. The first NULL is because pointer_to_recv is not pointing anywhere yet, second NULL is for the extent of the rank because
// pointer_to_recv is NULL and has no rank yet
CFI_establish(pointer_to_recv, NULL, CFI_attribute_allocatable, CFI_type_double, sizeof(double *), rank, NULL);
int to_recv_size = 0;
std::cout<<"C++ is sending double array: "<<std::endl;
for(int i = 0; i < array_size; i++)
std::cout<<dbl_array_tosend[static_cast<size_t>(i)]<<std::endl;
std::cout<<"C++ is sending int array: "<<std::endl;
for(size_t i = 0; i < array_size; i++)
std::cout<<int_array_tosend[i]<<std::endl;
dummy_subroutine(array_size, array_size, &dbl_array_tosend[0], &int_array_tosend[0], pointer_to_recv, &to_recv_size);
dbl_to_recv = (double *) pointer_to_recv->base_addr;
std::cout<<"C++ recv the array: "<<std::endl;
for(size_t i = 0; i < to_recv_size; i++)
std::cout<<dbl_to_recv[i]<<std::endl;
// Clear the allocated data
CFI_deallocate(pointer_to_recv);
return 0;
}
Fortran
module sample
use, intrinsic :: iso_c_binding
implicit none
private
public :: dummy_subroutine
contains
subroutine dummy_subroutine(real_array_in_size, int_array_in_size, real_array_in, int_array_in, real_array_out, &
real_array_out_size) bind(C)
integer(c_int), intent(in), value :: real_array_in_size, int_array_in_size
real(c_double), dimension(real_array_in_size), intent(in) :: real_array_in
integer(c_int), dimension(int_array_in_size), intent(in) :: int_array_in
real(c_double), allocatable, intent(inout), target :: real_array_out(:)
integer(c_int), intent(inout) :: real_array_out_size
write(*, *) "Fortran recieved real array", real_array_in
write(*, *) "Fortran recieved integer array", int_array_in
real_array_out_size = 15
allocate(real_array_out(real_array_out_size))
write(*, *) "Fortran allocated the memory"
real_array_out = 1.3d0
write(*, *) "Fortran sent the array", real_array_out
end subroutine dummy_subroutine
end module sample
退出时我从 gfortran 得到的错误消息是:
*** stack smashing detected ***: ./build/gnuRelease/example terminated
======= Backtrace: =========
/lib64/libc.so.6(__fortify_fail+0x37)[0x7f5c680456e7]
/lib64/libc.so.6(+0x1186a2)[0x7f5c680456a2]
./build/gnuRelease/example(main+0x349)[0x401609]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f5c67f4f445]
./build/gnuRelease/example[0x401694]
======= Memory map: ========
00400000-00405000 r-xp 00000000 00:2b 2398683777 /home/elads/cpp_template_project/build/gnuRelease/example_3d6066b1_with_diff_gnuRelease
00605000-00606000 r--p 00005000 00:2b 2398683777 /home/elads/cpp_template_project/build/gnuRelease/example_3d6066b1_with_diff_gnuRelease
00606000-00607000 rw-p 00006000 00:2b 2398683777 /home/elads/cpp_template_project/build/gnuRelease/example_3d6066b1_with_diff_gnuRelease
016d1000-01703000 rw-p 00000000 00:00 0 [heap]
7f5c67f2d000-7f5c680f0000 r-xp 00000000 fd:00 154314 /usr/lib64/libc-2.17.so
7f5c680f0000-7f5c682ef000 ---p 001c3000 fd:00 154314 /usr/lib64/libc-2.17.so
7f5c682ef000-7f5c682f3000 r--p 001c2000 fd:00 154314 /usr/lib64/libc-2.17.so
7f5c682f3000-7f5c682f5000 rw-p 001c6000 fd:00 154314 /usr/lib64/libc-2.17.so
7f5c682f5000-7f5c682fa000 rw-p 00000000 00:00 0
7f5c682fa000-7f5c68310000 r-xp 00000000 00:29 2412738746 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgcc_s.so.1
7f5c68310000-7f5c68510000 ---p 00016000 00:29 2412738746 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgcc_s.so.1
7f5c68510000-7f5c68511000 r--p 00016000 00:29 2412738746 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgcc_s.so.1
7f5c68511000-7f5c68512000 rw-p 00017000 00:29 2412738746 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgcc_s.so.1
7f5c68512000-7f5c68613000 r-xp 00000000 fd:00 154322 /usr/lib64/libm-2.17.so
7f5c68613000-7f5c68812000 ---p 00101000 fd:00 154322 /usr/lib64/libm-2.17.so
7f5c68812000-7f5c68813000 r--p 00100000 fd:00 154322 /usr/lib64/libm-2.17.so
7f5c68813000-7f5c68814000 rw-p 00101000 fd:00 154322 /usr/lib64/libm-2.17.so
7f5c68814000-7f5c689dd000 r-xp 00000000 00:29 2412738751 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libstdc++.so.6.0.27
7f5c689dd000-7f5c68bdc000 ---p 001c9000 00:29 2412738751 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libstdc++.so.6.0.27
7f5c68bdc000-7f5c68be7000 r--p 001c8000 00:29 2412738751 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libstdc++.so.6.0.27
7f5c68be7000-7f5c68bea000 rw-p 001d3000 00:29 2412738751 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libstdc++.so.6.0.27
7f5c68bea000-7f5c68bed000 rw-p 00000000 00:00 0
7f5c68bed000-7f5c68c32000 r-xp 00000000 00:29 2403246729 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libquadmath.so.0.0.0
7f5c68c32000-7f5c68e31000 ---p 00045000 00:29 2403246729 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libquadmath.so.0.0.0
7f5c68e31000-7f5c68e32000 r--p 00044000 00:29 2403246729 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libquadmath.so.0.0.0
7f5c68e32000-7f5c68e33000 rw-p 00045000 00:29 2403246729 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libquadmath.so.0.0.0
7f5c68e33000-7f5c690be000 r-xp 00000000 00:29 2403246737 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgfortran.so.5.0.0
7f5c690be000-7f5c692be000 ---p 0028b000 00:29 2403246737 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgfortran.so.5.0.0
7f5c692be000-7f5c692bf000 r--p 0028b000 00:29 2403246737 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgfortran.so.5.0.0
7f5c692bf000-7f5c692c1000 rw-p 0028c000 00:29 2403246737 /software/x86_64/3.10.0/gcc/9.2.0/lib64/libgfortran.so.5.0.0
7f5c692c1000-7f5c692e3000 r-xp 00000000 fd:00 154307 /usr/lib64/ld-2.17.so
7f5c694bf000-7f5c694c4000 rw-p 00000000 00:00 0
7f5c694dd000-7f5c694e2000 rw-p 00000000 00:00 0
7f5c694e2000-7f5c694e3000 r--p 00021000 fd:00 154307 /usr/lib64/ld-2.17.so
7f5c694e3000-7f5c694e4000 rw-p 00022000 fd:00 154307 /usr/lib64/ld-2.17.so
7f5c694e4000-7f5c694e5000 rw-p 00000000 00:00 0
7ffcbb588000-7ffcbb5af000 rw-p 00000000 00:00 0 [stack]
7ffcbb5ed000-7ffcbb5ef000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted
使用地址清理,错误消息是
=================================================================
==10376==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc2595b8b0 at pc 0x000000402453 bp 0x7ffc2595ab70 sp 0x7ffc2595ab68
WRITE of size 8 at 0x7ffc2595b8b0 thread T0
#0 0x402452 in dummy_subroutine sample.f90:19
#1 0x403129 in main csample.cc:35
#2 0x7f414f8c1f89 in __libc_start_main ../csu/libc-start.c:308
#3 0x401639 in _start (a.out+0x401639)
Address 0x7ffc2595b8b0 is located in stack of thread T0 at offset 320 in frame
#0 0x402b8e in main csample.cc:12
This frame has 8 object(s):
[48, 49) '<unknown>'
[64, 65) '<unknown>'
[80, 84) '<unknown>'
[96, 100) 'to_recv_size' (line 28)
[112, 120) '<unknown>'
[144, 168) 'dbl_array_tosend' (line 16)
[208, 232) 'int_array_tosend' (line 17)
[272, 320) 'c_desc' (line 20) <== Memory access at offset 320 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow sample.f90:19 in dummy_subroutine
Shadow bytes around the buggy address:
0x100004b236c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100004b236d0: f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3
0x100004b236e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
0x100004b236f0: f1 f1 f1 f1 f8 f2 f8 f2 f8 f2 04 00 f8 f2 f2 f2
0x100004b23700: 00 00 00 f2 f2 f2 f2 f2 00 00 00 f2 f2 f2 f2 f2
=>0x100004b23710: 00 00 00 00 00 00[f3]f3 f3 f3 00 00 00 00 00 00
0x100004b23720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100004b23730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100004b23740: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100004b23750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100004b23760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==10376==ABORTING