I'm trying to write a mixed-language (C++/Fortran) code in which memory passed from C++ to the Fortran subroutine may or may not be used and so in fact may or may not be allocated. The behavior inside the Fortran subroutine should be determined by an additional integer flag that is passed from C++ to Fortran. The problem that I am encountering seems to occur primarily with the Intel compiler (2022.1.2, 2022.1.0, 2021.4.0, 2021.1) combined with optimization (-O2). In that case, the compiler ignores my conditional statement and chooses to make an assignment from the unallocated memory, triggering a segmentation fault.
This example, consisting of one .cpp file, one .F90 file, and one Makefile, should demonstrate the problem: The line in the Fortran code that says "my_number = numbers" should never be executed based on the surrounding conditional, but with optimization, the line triggers a segmentation fault anyway.
Is there a way to prevent the optimization from ignoring my conditional or a better way to handle this overall (while maintaining the mixed-language paradigm)?
main.cpp:
extern "C" {
void test_module_mp_test_routine_(int* numbers,int* allocated);
}
int main(void)
{
int* numbers(0);
bool allocated(numbers);
int allocated_int(allocated);
test_module_mp_test_routine_(numbers,&allocated_int);
return 0;
}
test_module.F90:
! ============================================================
module test_module
! ============================================================
implicit none
private
save
public :: test_routine
contains
! ============================================================
subroutine test_routine(numbers,allocated_int)
! ============================================================
implicit none
integer :: numbers,allocated_int
logical :: have_numbers
integer :: my_number
continue
have_numbers = (allocated_int == 1)
my_number = 0
if (have_numbers) then
my_number = numbers
end if
write(*,*)"allocated_int = ",allocated_int
if (have_numbers) then
write(*,*)"my_number = ",my_number
end if
return
end subroutine test_routine
end module test_module`
Makefile:
CXX=icpc
FORT=ifort
main: main.cpp test_module.o
$(CXX) -O2 -o $@ $^ -lifcore
test_module.o: test_module.F90
$(FORT) -O2 -c $<
clean:
rm -f test_module.{o,mod} main