我正在使用与 LLVM 类似的 Java 语言编写编译器。但是,我在分配内存和引用它时遇到了一些困难。这是我尝试编译的代码:
class Node {
Node a;
}
int main () {
Node n = new Node;
n.a = new Node;
return 0;
}
我生成 LLVM 代码(对不起,它不能更短):
%struct.Node 中的 i32、i32* 用于在将来保存一些内部信息
declare i8* @malloc(i32)
%struct.Node = type { i32, i32* , %struct.Node*}
define i32 @main()
{
%temp_0 = call i8* @malloc(i32 12)
%temp_1 = bitcast i8* %temp_0 to %struct.Node*
call void @Node_init(%struct.Node* %temp_1)
%var_0 = alloca %struct.Node*
store %struct.Node* %temp_1, %struct.Node** %var_0
%temp_3= load %struct.Node** %var_0
%temp_4 = getelementptr inbounds %struct.Node* %temp_3, i32 0, i32 2
%temp_6 = call i8* @malloc(i32 12)
%temp_7 = bitcast i8* %temp_6 to %struct.Node*
call void @Node_init(%struct.Node* %temp_7)
store %struct.Node* %temp_7, %struct.Node** %temp_4
ret i32 0
}
define void @Node_init(%struct.Node* %temp_0)
{
%var_0 = alloca %struct.Node*
%temp_10 = getelementptr inbounds %struct.Node* %temp_0, i32 0
store %struct.Node* %temp_10, %struct.Node** %var_0
%temp_11= load %struct.Node** %var_0
%temp_12 = getelementptr inbounds %struct.Node* %temp_11, i32 0, i32 2
store %struct.Node* null, %struct.Node** %temp_12
ret void
}
在执行期间 valgrind 显示错误:
==3217== Invalid write of size 4
==3217== at 0x5A8901F: ???
==3217== Address 0x570dff8 is 4 bytes after a block of size 12 alloc'd
==3217== at 0x402BB7A: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3217== by 0x5A8901E: ???
这很奇怪,因为当我删除其中一行时:
call void @Node_init(%struct.Node* %temp_7)
store %struct.Node* %temp_7, %struct.Node** %temp_4
问题消失了。也有替换的程序
class Node {
Node a;
}
和
class Node {
int a;
}
并且对对象字段执行类似的操作不会导致任何错误。