代码之家  ›  专栏  ›  技术社区  ›  zoecarver

分段故障-访问从llvm ir代码传递的数组元素

  •  1
  • zoecarver  · 技术社区  · 6 年前

    我有一个程序运行良好,当我运行它使用C++,但是,当我把它从我的LLVM红外代码,它不工作。

    函数(library/library.cpp)

    extern "C" DLLEXPORT double *DOT(double A[3][3], double B[3][3]) {
      std::cout << A[0][0] << std::endl;
    ...
    }
    

    llvm-ir(输出.ll)

    declare [3 x double] @DOT([3 x [3 x double]], [3 x [3 x double]])
    ...
    %a1 = load [3 x [3 x double]], [3 x [3 x double]]* %a
    %b2 = load [3 x [3 x double]], [3 x [3 x double]]* %b
    %calltmp = call [3 x double] @DOT([3 x [3 x double]] %a1, [3 x [3 x double]] %b2)
    

    我没有包括完整的程序来节省空间,但如果它是有用的,只要问,我会更新的问题。

    错误(已生成)

    [1]    3086 segmentation fault  ./built
    

    我使用以下命令编译代码:

    clang++ library/library.cpp out.ll -o built
    

    信息

    这项工作:

    std::cout << A[0] << std::endl; // 0x1
    

    这不会:

    std::cout << A[0][0] << std::endl;
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   sepp2k    6 年前

    您用错误的签名声明了您的函数:

    首先,函数返回指向double的指针,而不是double数组。这很清楚,因为C++代码字面上说 double * 作为返回类型。

    不太明显的问题是,参数的类型是“指向双精度数组的指针”,而不是“指向双精度数组的数组”。这是因为C和C++不支持数组类型的函数参数,但非常令人困惑地决定,仍然接受参数列表中数组类型的语法,而简单地将其视为声明指针。所以 double A[3][3] 在一个参数列表中(仅此而已),有一种更令人困惑的写入方式 double (*A)[3] .

    所以最后,你的声明应该是:

    declare double* @DOT([3 x double]*, [3 x double]*)
    

    因此,您还应该将您的呼叫代码更改为呼叫 @DOT 指针类型正确。