如何通过LLVM将数组正确传递给C函数?解决调用崩溃问题
LLVM传递数组给C函数崩溃的原因及解决方法
问题场景
尝试创建一个包含两个64位元素的数组,存储到局部变量后加载并传递给C函数。调用接收指针参数的C函数时程序崩溃,但调用接收单个64位值的C函数时可正常打印数组首个元素。
原始LLVM字节码
define i32 @main() { %1 = alloca [2 x i64], align 8 store [2 x i64] [i64 1, i64 10], [2 x i64]* %1, align 4 %2 = load [2 x i64], [2 x i64]* %1, align 4 call void @printType([2 x i64] %2) ret i32 0 }
崩溃的C函数
void printType(int64_t* parts) { printf("%ld\n", parts[0]); }
可正常运行的C函数
void printType(int64_t parts) { printf("%ld\n", parts); }
核心问题
你忽略了LLVM数组类型与C数组参数的传递规则差异:
- 在LLVM中,
[2 x i64]是完整的数组值类型,当你通过call void @printType([2 x i64] %2)调用函数时,是把整个数组的两个64位值按值传递到函数栈中。 - 但你的C函数
printType(int64_t* parts)期望接收的是指针类型(数组的首地址),此时栈中的两个64位值会被C函数当作内存指针解析,这显然是无效地址,访问时必然触发崩溃。 - 第二个C函数能正常运行只是巧合:它接收单个64位值,刚好读取了栈中传递的数组第一个元素的值,但这并不是正确的数组传递方式。
解决方案
需要传递数组的指针而非数组本身的值,同时确保LLVM中的指针类型与C函数参数类型匹配。修改后的LLVM字节码如下:
define i32 @main() { %1 = alloca [2 x i64], align 8 store [2 x i64] [i64 1, i64 10], [2 x i64]* %1, align 8 ; 将数组指针转换为i64*类型,匹配C函数的int64_t*参数 %arr_ptr = bitcast [2 x i64]* %1 to i64* call void @printType(i64* %arr_ptr) ret i32 0 }
C函数保持原指针版本即可:
#include <stdio.h> void printType(int64_t* parts) { printf("%ld\n", parts[0]); }
说明
bitcast指令用于转换指针类型:LLVM中[2 x i64]*(数组指针)和i64*(元素指针)的内存地址相同,但类型不同,显式转换后才能匹配C函数的参数类型。- 直接传递数组指针给C函数,函数就能正确访问数组的首元素,避免无效地址访问导致的崩溃。
内容的提问来源于stack exchange,提问作者Samuel Rowe
相关产品推荐
相关产品推荐

