You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 00:05:13