Фортран 2018 смешанных с ++ ошибок указателя нулевого сегмента - PullRequest
2 голосов
/ 25 февраля 2020

У меня есть простая программа, которая объединяет C ++ и Fortran с использованием новой семантики Fortran 2018. Мой пример основан на комментарии № 12 в https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/697150. Мой пример прекрасно работает с использованием компилятора Intel (2019 update5), но когда я использую флаг check pointers, он вылетает с ошибкой seg, когда я вызываю подпрограмму 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
...