Skip to content

Commit

Permalink
Update gethostname example (#36082)
Browse files Browse the repository at this point in the history
Add `GC.@preserve` to code and a short explanation
  • Loading branch information
mzaffalon committed May 30, 2020
1 parent a5c08c4 commit 7301dc6
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions doc/src/manual/calling-c-and-fortran-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,19 +142,24 @@ function gethostname()
hostname, sizeof(hostname))
Base.systemerror("gethostname", err != 0)
hostname[end] = 0 # ensure null-termination
return unsafe_string(pointer(hostname))
return GC.@preserve hostname unsafe_string(pointer(hostname))
end
```

This example first allocates an array of bytes. It then calls the C library function `gethostname`
to populate the array with the hostname. Finally, it takes a pointer to the hostname buffer, and converts the
pointer to a Julia string, assuming that it is a NUL-terminated C string. It is common for C libraries
to use this pattern of requiring the caller to allocate memory to be passed to the callee and
populated. Allocation of memory from Julia like this is generally accomplished by creating an
uninitialized array and passing a pointer to its data to the C function. This is why we don't
use the `Cstring` type here: as the array is uninitialized, it could contain NUL bytes. Converting
to a `Cstring` as part of the [`ccall`](@ref) checks for contained NUL bytes and could therefore
throw a conversion error.
to populate the array with the hostname. Finally, it takes a pointer to the hostname buffer, and
converts the pointer to a Julia string, assuming that it is a NUL-terminated C string.

It is common for C libraries to use this pattern of requiring the caller to allocate memory to be
passed to the callee and populated. Allocation of memory from Julia like this is generally
accomplished by creating an uninitialized array and passing a pointer to its data to the C function.
This is why we don't use the `Cstring` type here: as the array is uninitialized, it could contain
NUL bytes. Converting to a `Cstring` as part of the [`ccall`](@ref) checks for contained NUL bytes
and could therefore throw a conversion error.

Deferencing `pointer(hostname)` with `unsafe_string` is an unsafe operation as it requires access to
the memory allocated for `hostname` that may have been in the meanwhile garbage collected. The macro
[`GC.@preserve`](@ref) prevents this from happening and therefore accessing an invalid memory location.

## Creating C-Compatible Julia Function Pointers

Expand Down

8 comments on commit 7301dc6

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily package evaluation, I will reply here when finished:

@nanosoldier runtests(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your package evaluation job has completed - possible new issues were detected. A full report can be found here. cc @maleadt

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily package evaluation, I will reply here when finished:

@nanosoldier runtests(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your package evaluation job has completed - possible issues were detected. A full report can be found here. cc @maleadt

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

Please sign in to comment.