C++向Fortran传递字符串数组出现段错误,求解决方法
解决C++向Fortran传递字符串数组的段错误问题
段错误原因分析
Fortran中character(len=100) arr(3)是连续存储的固定长度字符串数组:3个字符串每个占100字节,总内存大小为3100字节,传递给C/C时会直接传递数组的起始内存地址。而原C代码中用char** arr接收,会把这块连续内存的起始地址当成指针数组(每个元素是char)来访问,完全不符合Fortran的内存布局,直接导致非法内存访问,触发段错误。
修正后的代码实现
Fortran代码(main.f90)
原代码的打印逻辑本身是正确的,无需修改:
program main implicit none character(len=100) arr(3) call get_string_array(arr, 100, 3) write(*,'(3(a,3x))') arr end
C++代码(cpp_func.cpp)
修改函数参数类型,通过内存偏移定位每个字符串的起始地址:
#include <cstring> #include <algorithm> using namespace std; void ConvertToFortran(char* fstring, size_t fstring_len, const char* cstring) { size_t inlen = strlen(cstring); size_t cpylen = min(inlen, fstring_len); fill(fstring, fstring + fstring_len, ' '); copy(cstring, cstring + cpylen, fstring); } extern "C" { // 第一个参数改为char*,对应Fortran连续内存的起始地址 void get_string_array_(char* arr, int len, int n) { const char* strings[] = {"duma1", "duma2", "duma3"}; for (int i = 0; i < n; i++) { // 计算第i个字符串的起始地址:arr + i * len char* current_str = arr + i * len; ConvertToFortran(current_str, len, strings[i]); } } }
编译运行
保持原编译命令即可:
ifx -c main.f90 icx -c cpp_func.cpp ifx main.o cpp_func.o ./a.out # Linux/macOS下运行,Windows下执行a.exe
运行后会输出:duma1 duma2 duma3
更规范的现代Fortran交互方案(ISO_C_BINDING)
为彻底避免类型不匹配问题,建议使用Fortran的ISO_C_BINDING模块定义显式接口,实现类型安全的跨语言调用:
改进后的Fortran代码(main.f90)
program main use, intrinsic :: iso_c_binding implicit none interface subroutine get_string_array(arr, len, n) bind(C, name='get_string_array') import :: c_char, c_int character(kind=c_char), intent(out) :: arr(*) integer(c_int), value, intent(in) :: len, n end subroutine get_string_array end interface character(len=100, kind=c_char) arr(3) call get_string_array(arr, 100_c_int, 3_c_int) write(*,'(3(a,3x))') arr end program main
改进后的C++代码(cpp_func.cpp)
#include <cstring> #include <algorithm> extern "C" { void get_string_array(char* arr, int len, int n) { const char* strings[] = {"duma1", "duma2", "duma3"}; for (int i = 0; i < n; i++) { char* current_str = arr + i * len; std::fill(current_str, current_str + len, ' '); const char* src = strings[i]; std::size_t src_len = std::strlen(src); std::size_t copy_len = std::min(static_cast<std::size_t>(len), src_len); std::copy(src, src + copy_len, current_str); } } }
这种方式通过显式接口定义,确保Fortran和C++的参数类型完全匹配,从根源避免内存布局不匹配的问题。
内容的提问来源于stack exchange,提问作者TobiR
相关产品推荐
相关产品推荐

