Annotate alloc/free open/close functions with compiler attributes#13457
Annotate alloc/free open/close functions with compiler attributes#13457gasche merged 3 commits intoocaml:trunkfrom
Conversation
|
I like the idea. I looked at the document to figure out what the numbers in Style nitpick: I'm not fond of the fact that sometimes the user is passing some constant numbers by parameter (the |
|
Do we have other pairs of allocators/deallocators functions that could benefit from these annotations? If not, I'm tending towards making all the parameters hidden. If there are, or if we could have some use for them in the future, explicit parameters (as the expense of adding more code to the headers) is probably better. |
|
The documentation mentions that, say, |
f82de5d to
de5bc27
Compare
caml_stat_* functions with compiler attributes|
I've changed the parameters to always be passed by the user. I've found two new pairs of functions to annotate. |
de5bc27 to
029f83e
Compare
gasche
left a comment
There was a problem hiding this comment.
This looks nice to me, but I would like to see more documentation before merging: this is new, and I expect it could be confusing to people reading our C code and unfamiliar with this.
The documentation should go in misc.h, where the macros are defined. It should at the very least include a URL pointing to a documentation for these weird attributes, to find out for example what the mysterious ptr_index number means. In addition, I think it would be nice if you could write a short documentation comment for each macro separately, for example something like:
/* [CAMLcalloc(dealloc, p, 1, 2)] allocates a memory block whose size
is given by the product of its first and second argument, and must be deallocated
by passing as the [p]-th argument of the function [dealloc(...)]. */
#define CAMLcalloc(deallocator,ptr_index,alloc_size_N,alloc_size_M,...) \
CAMLalloc(deallocator, ptr_index) \
__attribute__ ((alloc_size(alloc_size_N,alloc_size_M)))
This helps the compiler optimize code, and static analysis by detecting potential mismatches in alloc/free pairs. - malloc > The malloc attribute indicates that the function acts like a system > memory allocation function, returning a pointer to allocated storage > disjoint from the storage for any other object accessible to the > caller. https://clang.llvm.org/docs/AttributeReference.html#malloc > Associating a function with a deallocator helps detect calls to > mismatched allocation and deallocation functions and diagnose them > under the control of options such as -Wmismatched-dealloc. It also > makes it possible to diagnose attempts to deallocate objects that > were not allocated dynamically, by -Wfree-nonheap-object. To > indicate that an allocation function both satisifies the nonaliasing > property and has a deallocator associated with it, both the plain > form of the attribute and the one with the deallocator argument must > be used. > The warnings guarded by -fanalyzer respect allocation and > deallocation pairs marked with the malloc. https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute Note that the malloc attribute can only be applied to functions returning pointers. The OCaml value type is a typedef to an integer type, and the C compiler will refuse applying the attribute to a function returning an OCaml value. - nodiscard / warn_unused_result Prevent memory leaks by warning if the result of an allocation is ignored. https://clang.llvm.org/docs/AttributeReference.html#nodiscard-warn-unused-result - alloc_align > GCC uses this information to improve pointer alignment analysis. https://clang.llvm.org/docs/AttributeReference.html#alloc-align https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005falign-function-attribute - alloc_size > GCC uses this information to improve the results of > __builtin_object_size. https://clang.llvm.org/docs/AttributeReference.html#alloc-size https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute - returns_nonnull > lets the compiler optimize callers based on the knowledge that the > return value will never be null. > The analyzer considers the possibility that an allocation function > could fail and return null. […] If the allocator always returns > non-null, use __attribute__ ((returns_nonnull)) to suppress these > warnings. https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-returns_005fnonnull-function-attribute
029f83e to
b516b1a
Compare
|
Thanks for the review! I've added documentation. Is it a bit verbose? |
gasche
left a comment
There was a problem hiding this comment.
The new documentation is perfect, thanks!
|
As far as I can see this PR fails to compile on both too recent and too ancient version of gcc. Thus it needs more testing and I am planning to revert it soon. |
|
Oops, sorry. Yes, please feel free to revert it. The conditionals on |
Could you point me to these failures? I've successfully build this branch with GCC 11.5 (earliest maintained release) and GCC 14.2 (latest maintained release). I'm fine with guarding the definitions with |
|
With ubuntu 24.04.1 and gcc 13.2.0 (so not very recent, sorry) For old gcc, the inria CI has seen the failure on and fails with |
|
Indeed the
and it's not possible to test with As for the error with GCC 13, the error could be related to this bug report. GCC doesn't see that # syntax=docker/dockerfile:1
FROM ubuntu:24.04
ADD git@github.com:MisterDA/ocaml.git#caml_stat-annotations /tmp/ocaml
WORKDIR /tmp/ocaml
RUN apt-get -y update && apt-get install -y build-essential git
RUN ./configure --disable-ocamldoc
RUN patch -Np1 <<"EOF"
diff --git a/runtime/startup_byt.c b/runtime/startup_byt.c
index 04bb87c435..2af6089753 100644
--- a/runtime/startup_byt.c
+++ b/runtime/startup_byt.c
@@ -214,7 +214,7 @@ static char * read_section(int fd, struct exec_trailer *trail,
char * data;
len = caml_seek_optional_section(fd, trail, name);
- if (len == -1) return NULL;
+ if (len <= -1) return NULL;
data = caml_stat_alloc(len + 1);
if (read(fd, data, len) != len)
caml_fatal_error("error reading section %s", name);
@@ -232,7 +232,7 @@ static char_os * read_section_to_os(int fd, struct exec_trailer *trail,
wchar_t * wdata;
len = caml_seek_optional_section(fd, trail, name);
- if (len == -1) return NULL;
+ if (len <= -1) return NULL;
data = caml_stat_alloc(len + 1);
if (read(fd, data, len) != len)
caml_fatal_error("error reading section %s", name);
EOF
RUN make -j$(nproc)The bug doesn't appear in GCC 14. We could either:
|
|
Before I forget, you should not hesitate to request an access right at Inria CI. |
|
Maybe it's not too hard to write a small, self-contained |
|
Well, the second problem seems to be a limitation of the compiler's static analyzer. It's not possible to account for all past (and future!) compiler bugs… but I can build this branch with GCC 14 and any version of clang, and I propose to keep this restriction with the hope that if future GCC warns, it'll be a useful warning. |
This helps the C compiler optimize code, and helps static analysis by detecting potential mismatches in alloc/free pairs.
mallochttps://clang.llvm.org/docs/AttributeReference.html#malloc
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
Note that the
mallocattribute can only be applied to functions returning pointers. The OCamlvaluetype is a typedef to an integer type, and the C compiler will refuse applying the attribute to a function returning an OCaml value (one could want to check if custom values are finalized).nodiscard/warn_unused_resultPrevent memory leaks by warning if the result of an allocation is ignored.
https://clang.llvm.org/docs/AttributeReference.html#nodiscard-warn-unused-result
alloc_alignhttps://clang.llvm.org/docs/AttributeReference.html#alloc-align
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005falign-function-attribute
alloc_sizehttps://clang.llvm.org/docs/AttributeReference.html#alloc-size
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
returns_nonnullhttps://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-returns_005fnonnull-function-attribute
Invoked on the following test program, GCC 14.2.1 reports:
Simply using
-Wallturns on more checks. The-fanalyzerwarning has both false positive and false negatives and I'm not turning it on on the codebase. I believe this code may help users writing C FFI code for OCaml. No warnings have been raised on the current trunk or on Lwt. Let me know if there are packages containing C code that could be tested.glibc has annotated functions in
malloc/malloc.h, but as we're keeping track of C heap allocations, the compiler cannot propagate the annotations to the call sites ofcaml_stat_*functions.I don't have insights on whether code gen has improved or worsened.
I tried to keep the macro definitions as condensed as possible, let me know if you'd prefer an alternate definition.