У меня проблемы с segfaults при доступе к массиву в C, который выделен в файле Fortran ниже. Есть несколько артефактов отладки, например, тот факт, что записи в файл не пишут ничего значимого, и я инициализирую переменную i
, которую никогда не использую.
Однако я обнаружил следующее:
- Не инициализируется
i
(но все еще объявляет): нет segfault - Не открывать файл в C: нет segfault
- Отсутствие печати
HESS
(неHESS_COPY
) в другом месте кода: нет segfault - Объявление и инициализация
i
с другим именем: segfault
Кто-нибудь знает, что может вызвать такое поведение? Сам 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