在GC.enable(true)时在Julia中使用ccall进行段错误

时间:2019-01-26 03:59:46

标签: c shared-libraries julia

我遇到了一个奇怪的问题,即我与共享库连接时,当我尝试使用ccall时会遇到段错误。我已经用Python重写了代码,但是没有任何问题。它也仅在GC.enable(true)时发生。如果我在运行任何GC.enable(false)函数之前先运行ccall,则一切正常。

奇怪的是,当我运行以下命令时:

GC.enable(false)
var1 = Ref(...)
var2 = pointer(...)
ccall(...)
GC.enable(true)

它仍然存在段错误。

我在此GitHub link上发布了一个最小的工作示例。我希望有人可以看看并告诉我我做错了什么?

此外,如果有人可以在使用C中的不同类型的模式时在Julia中使用ccall时提供最佳实践建议,那将非常有用。目前,我所获得的最多信息是官方文档,该文档很有用,但并不涵盖我与C代码交互时看到的所有模式。

1 个答案:

答案 0 :(得分:3)

您可以使用GC.@preserve来临时防止变量被垃圾回收:

var1
var2

GC.@preserve var1 var2 begin
    ccall(...)
    var3 = unsafe_xxx
end

var3

真正的原因是您的共享库需要ResultPtr才能正确初始化,而您刚遇到一些未定义的行为:

REPL

julia> Ref{Ptr{Cstring}}(C_NULL)
Base.RefValue{Ptr{Cstring}}(Ptr{Cstring} @0x0000000000000000)

julia> Ref{Ptr{Cstring}}()
Base.RefValue{Ptr{Cstring}}(Ptr{Cstring} @0x000000011b98ca70)  # this results in segfaults

CMD

➜  opendss-debug git:(master) ✗ julia -e '@show Ref{Ptr{Cstring}}()'
Ref{Ptr{Cstring}}() = Base.RefValue{Ptr{Cstring}}(Ptr{Cstring} @0x0000000000000000)