[llvm-dev] [RFC] Adding support for marking allocator functions in LLVM IR

James Y Knight via llvm-dev
Thu, 06 Jan 2022 16:10:57 -0000

On Wed, Jan 5, 2022 at 5:32 PM Augie Fackler via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> In addition to the benefits for Rust, the LLVM optimizer could also be
> improved to not optimize away defects like
>
> {
>
>   auto *foo = new Thing();
>
>   free(foo);
>
> }
>
> which would then correctly crash instead of silently “working” until
> something actually uses the allocation. Similarly, there’s a potential
> defect when only one side of an overridden operator::new and
> operator::delete is visible to the optimizer and inlineable, which can look
> indistinguishable from the above after inlining.
>

I think this is important to note -- tracking the pairing is something we
should be doing already with the existing hardcoded list, as well. E.g.
compile the following example with -O1 (https://godbolt.org/z/WsYKcexYG).

When compiling "main", at first we cannot see the matched new/delete
pair,
because delete is hidden in the "deleteit" function. Then, we run the
inliner, which inlines the "operator new" and "deleteit"
functions. Now,
main has a call to malloc followed by ::operator delete, which we proceed
to remove, because they're allocation functions. But they're *unmatched*
allocation functions, so this weirdly ends up skipping the side-effects of
our custom operator delete, but NOT those of our custom operator new.

#include <stdlib.h>
#include <stdio.h>

int allocs = 0;

void *operator new(size_t n) {
allocs++;
void *mem = malloc(n);
if (!mem) abort();
return mem;
}

__attribute__((noinline)) void operator delete(void *mem) noexcept {
allocs--;
free(mem);
}

void deleteit(int*i) { delete i; }
int main() {
int*i = new int;
deleteit(i);
if (allocs != 0)
printf("MEMORY LEAK! allocs: %d\n", allocs);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20220106/9f78e6f5/attachment-0001.html>