On the garbage collection

I read the thread over again.

Could that be a “rule of thumb” for a Julia programmer using pointers?

“to be safe, enclose dereferencing use of a pointer into memory of x in a GC.@preserve x block”.

You said clearly that pointer computation outside (before) the GC.@preserve block is safe. This is a BIG difference between Julia and other languages, e.g. Java with a GC which relocates valid java memory blocks to compactify managed Java heaps.

Sorry for another example - it is not meant as efficient code, it solely demonstrates decoupled computing and dereferencing of a pointer variable and my understanding of “memory belongs to object pd”.

Are both uses of GC.@preserved in the following code snippet correct and necessary?

mutable struct PreservedDemo
    s:: String # private instance, only changed by constructor and setstring!
    p:: Ptr{UInt8}  # private instance, only changed by constructor and setstring!
    PreservedDemo(s::String) = new(s,pointer(s))
end

# pointer computation decoupled from pointer dereferencing
function setstring!(pd::PreservedDemo,s::String)
    pd.s = s
    pd.p = pointer(s)
end

# protect dereferencing of pd.p which points to memory belonging (indirectly) to pd
function codeunit1(pd::PreservedDemo, i::Integer)
    # boundschecks ommitted to keep example short
    GC.@preserve pd unsafe_load(pd.p+(i-1))
end

# protect dereferencing of pd.p which points to memory belonging to pd.s
function codeunit2(pd::PreservedDemo, i::Integer)
    # boundschecks ommitted to keep example short
    s = pd.s
    GC.@preserve s unsafe_load(pd.p+(i-1))
end

# Testcode
q = PreservedDemo("hello")
codeunit1(q,2) # hex 'e'
codeunit1(q,4) # hex 'l'