If the goal is to experiment to see if making this change is
sufficiently valuable to either regress heap leak checkers or create a
divergence where this is configurable/appears only in certain modes -
then I'd say having a flag (maybe even an internal/cc1 only flag) is
the right first step, enabling data to be gathered to help inform the
design discussion.
> _______________________________________________
> LLVM Developers mailing list
> llvm...@lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
What was the original motivation for making the change - given the
gains are unclear? Might help frame what the right path forward is.
If the goal is to experiment to see if making this change is
sufficiently valuable to either regress heap leak checkers or create a
divergence where this is configurable/appears only in certain modes -
then I'd say having a flag (maybe even an internal/cc1 only flag) is
the right first step, enabling data to be gathered to help inform the
design discussion.
On Wed, Apr 14, 2021 at 9:39 AM Sterling Augustine via llvm-dev
<llvm...@lists.llvm.org> wrote:
>
> [Continuing discussion from https://reviews.llvm.org/D69428]
>
> Llvm is fairly conservative when eliminating global variables (or fields of such) that may point to dynamically allocated memory. This behavior is entirely to help leak checking tools such as Valgrind, Google's HeapLeakChecker, and LSAN, all of which treat memory that is reachable at exit as "not leaked", even though it will never be freed. Without these global variables to hold the pointer, the leak checkers can't determine that it is actually reachable, and will report a leak. Global variables that dynamically allocate memory but don't clean themselves up are fairly common in the wild, and various leak checkers have long not reported errors.
>
> This behavior was added all the way back in 2012 in https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120625/145646.html.
>
> https://reviews.llvm.org/D69428 removed this behavior, and I subsequently reverted it when many internal Google tests started failing, but I believe many other users who use leak checking will encounter errors when this hits more mainstream releases.
>
> So: What to do?
>
> Preventing a valid transformation (the global variables are never read and can be eliminated) to help the leak checkers leaves some performance and code size on the table. Just how much is unclear.
>
> On the other hand, having leak checkers suddenly start reporting failures where they didn't before also seems suboptimal. Cleaning this somewhat common scenario up is surprisingly difficult at the user level.
>
> Some possibilities:
>
> 1. Only do this at high optimization levels, say -O3. This would give aggressive users all the performance we can, but also make leak checkers report leaks sometimes, but not others.
>
> 2. Hide it behind a flag or configurable option. Users who care can set it as they prefer. Creates more confusing options, different testing matrices and such, but everyone can get the behaviour that they want.
>
> 3. Do it all the time, and users who encounter issues can clean up their code. Users get the most performance they possibly can, but have to clean up code or drop leak checking. Seems a little user hostile.
Most (all?) leak checkers support suppression files. Isn’t that sufficient for your use case?
Marking your leak roots with __attribute((used))__ is also an alternative.
I understand that leaking memory on purpose happens because it’s expensive to clean it up. But reachable memory may well be a true leak. So flagging it as such is useful. None of us has data about the % of reachable memory that is a true leak, so it’s not possible to argue what’s user friendly/hostile.
Programs that leak memory on purpose are often sophisticated. And sophisticated devs can handle a little bit of extra effort to hide those smarts I think.
Nuno
P.S.: The original patch went in almost a decade ago when the ecosystem was a bit less developed. It was always meant to be temporary.
[Continuing discussion from https://reviews.llvm.org/D69428]Llvm is fairly conservative when eliminating global variables (or fields of such) that may point to dynamically allocated memory. This behavior is entirely to help leak checking tools such as Valgrind, Google's HeapLeakChecker, and LSAN, all of which treat memory that is reachable at exit as "not leaked", even though it will never be freed. Without these global variables to hold the pointer, the leak checkers can't determine that it is actually reachable, and will report a leak. Global variables that dynamically allocate memory but don't clean themselves up are fairly common in the wild, and various leak checkers have long not reported errors.This behavior was added all the way back in 2012 in https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120625/145646.html.https://reviews.llvm.org/D69428 removed this behavior, and I subsequently reverted it when many internal Google tests started failing, but I believe many other users who use leak checking will encounter errors when this hits more mainstream releases.So: What to do?Preventing a valid transformation (the global variables are never read and can be eliminated) to help the leak checkers leaves some performance and code size on the table. Just how much is unclear.On the other hand, having leak checkers suddenly start reporting failures where they didn't before also seems suboptimal. Cleaning this somewhat common scenario up is surprisingly difficult at the user level.Some possibilities:1. Only do this at high optimization levels, say -O3. This would give aggressive users all the performance we can, but also make leak checkers report leaks sometimes, but not others.
2. Hide it behind a flag or configurable option. Users who care can set it as they prefer. Creates more confusing options, different testing matrices and such, but everyone can get the behaviour that they want.3. Do it all the time, and users who encounter issues can clean up their code. Users get the most performance they possibly can, but have to clean up code or drop leak checking. Seems a little user hostile.
Other possibilities?:
D69428 extended the function pointer cases to non-function-pointer
cases, which can be problematic.
On 2021-04-14, Nuno Lopes via llvm-dev wrote:
>Most (all?) leak checkers support suppression files. Isn’t that sufficient for your use case?
>Marking your leak roots with __attribute((used))__ is also an alternative.
>
>
>I understand that leaking memory on purpose happens because it’s expensive to clean it up. But reachable memory may well be a true leak. So flagging it as such is useful. None of us has data about the % of reachable memory that is a true leak, so it’s not possible to argue what’s user friendly/hostile.
As is, many code patterns in various projects can be affected by the
aggressive optimization. They may use a global pointer referencing an
allocated object as a replacement for a global variable with a
non-trivial destructor ([[clang::no_destroy]] :). Dynamic destruction is
not ordered across translation units, this can lead to all sorts of
static finalization order fiasco problems. If there are threads not
joined at exit time, some threads may access objects which have been
destructed.
In addition, the leak checker may be registered as an atexit callback
instead of running after all destructors have run.
If the leak checker is registered by atexit, normally it runs before
destructors. Even if you have sophisticated destructors which deallocate
objects properly, if you ignore them as roots, the checker will report
false positives.
>Programs that leak memory on purpose are often sophisticated. And sophisticated devs can handle a little bit of extra effort to hide those smarts I think.
>
>
>
>Nuno
>
>
>
>P.S.: The original patch went in almost a decade ago when the ecosystem was a bit less developed. It was always meant to be temporary.
>
>
>
>
>
>From: Sterling Augustine
>Sent: 14 April 2021 17:39
>To: llvm-dev <llvm...@lists.llvm.org>
>Subject: [llvm-dev] Eliminating global memory roots (or not) to help leak checkers
>
>
>
>[Continuing discussion from https://reviews.llvm.org/D69428]
>
>
>
>Llvm is fairly conservative when eliminating global variables (or fields of such) that may point to dynamically allocated memory. This behavior is entirely to help leak checking tools such as Valgrind, Google's HeapLeakChecker, and LSAN, all of which treat memory that is reachable at exit as "not leaked", even though it will never be freed. Without these global variables to hold the pointer, the leak checkers can't determine that it is actually reachable, and will report a leak. Global variables that dynamically allocate memory but don't clean themselves up are fairly common in the wild, and various leak checkers have long not reported errors.
>
>
>
>This behavior was added all the way back in 2012 in https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120625/145646.html.
>
>
>
>https://reviews.llvm.org/D69428 removed this behavior, and I subsequently reverted it when many internal Google tests started failing, but I believe many other users who use leak checking will encounter errors when this hits more mainstream releases.
>
>
>
>So: What to do?
>
>
>
>Preventing a valid transformation (the global variables are never read and can be eliminated) to help the leak checkers leaves some performance and code size on the table. Just how much is unclear.
>
>
>
>On the other hand, having leak checkers suddenly start reporting failures where they didn't before also seems suboptimal. Cleaning this somewhat common scenario up is surprisingly difficult at the user level.
>
>
>
>Some possibilities:
>
>
>
>1. Only do this at high optimization levels, say -O3. This would give aggressive users all the performance we can, but also make leak checkers report leaks sometimes, but not others.
>
>
>
>2. Hide it behind a flag or configurable option. Users who care can set it as they prefer. Creates more confusing options, different testing matrices and such, but everyone can get the behaviour that they want.
>
>
>
>3. Do it all the time, and users who encounter issues can clean up their code. Users get the most performance they possibly can, but have to clean up code or drop leak checking. Seems a little user hostile.
>
>
>
>Other possibilities?:
>
>_______________________________________________
Don't really have an opinion on the question as asked, but want
to point out an alternate framing. I will comment that the code
being removed looks more than a bit fragile.
From a very quick skim of the original code, it appears to be focused on DCE of globals. If we wanted to keep the "leak detector safe" semantic, but allow more aggressive optimization, we could re-imagine this as global SROA. We could deconstruct the struct/array/etc and keep only the fields which could potentially be allocation roots. We could also write an optimization which leverages the knowledge of the allocation root being otherwise unused to eliminate mallocs which are stored into them.
I haven't fully thought that through, but it seems like we have
quite a bit of room to optimize better without changing our
handling for the leak detectors.
Philip
Hi Sterling,I agree with the others: therIe are better (and more robust ways) to disable leak checkers. This only addresses one narrow case. The code is also super verbose and fragile looking. This is also eliminating an optimization.
> On Apr 19, 2021, at 5:24 AM, James Y Knight <jykn...@google.com> wrote:
>
> There is no problem (no leaks) in the code that users wrote, so adding code annotations (sanitizer suppression file, or attributes) is not a good solution to this issue. The problem is that this optimization introduces a "leak" (from the point of view of the leak checker), which wasn't there before. And in practice, this seems to cause a large number of false positives.
I think that “from the point of view of the leak checker” is the key thing there.
Code that this triggers *is* leaking memory, it was just silenced because the leak was spuriously reachable from a global. Global variables aren’t a preferred way to silence leak detectors, they have other ways to do so :)
> On Apr 19, 2021, at 4:52 PM, Sterling Augustine <saugu...@google.com> wrote:
>
> There may be other ways to disable leak checkers, but they put a burden on users that was not there before. Further, users who try leak checking with and without optimization will get different answers. The bug report will read: "clang at -O2 makes my program leak". And, as James notes, whether or not you need to suppress the leak depends on whether or not the optimizer does away with the variable. Subtle changes to the code that have nothing to do with memory allocation will appear to add or fix leaks. That is not something I would care to explain or document.
I can see that concern, but this isn’t a battle that we can win: optimizations in general can expose leaks.
IMO, If someone doesn’t want the global to be removed, they should mark it volatile. If they do want it removable, then they can use leak detector features to silence the warning.
> On Apr 20, 2021, at 9:12 AM, Sterling Augustine <saugu...@google.com> wrote:
>
> In order to understand how much benefit this change gives to code size, I built clang and related files with and without the patch, both with CMAKE_BUILD_TYPE=Release.
>
> clang itself gets about 0.4% smaller (from 145217124 to 144631078)
> lld gets about 1.85% smaller (from 101129181 to 99243810 bytes)
>
> Spot checking a few other random targets, in general, it seems that the benefits depend heavily on the coding style, but roughly, bigger the binary, the less benefit this brings.
>
> I suspect that a more aggressive pass as described by Philip Reames could capture a significant part of the benefit without sacrificing functionality. But that would require a more detailed study to be sure.
A ~2% reduction in code size is a huge win. I agree with your comment about it being different with different coding styles. I suspect that this is the sort of thing that will pay particularly for high abstraction code bases.
I don’t see why we would punish general code to make “code that is leaking where formerly not detected, and where users don’t want to mark the root as volatile”. This seems really unprincipled to me, and a slippery slope we can’t go down.
-Chris
"spuriously" reachable is quite questionable here. This way of writing
code is to make the allocation quite intentionally reachable from a
global.
For instance, one of the ways to disable global destruction: (
https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
)
"If all else fails, you can create an object dynamically and never
delete it by using a function-local static pointer or reference (e.g.,
static const auto& impl = *new T(args...);)."
(all else fails in a large enough codebase rather often... )
> > On Apr 19, 2021, at 4:52 PM, Sterling Augustine <saugu...@google.com> wrote:
> >
> > There may be other ways to disable leak checkers, but they put a burden on users that was not there before. Further, users who try leak checking with and without optimization will get different answers. The bug report will read: "clang at -O2 makes my program leak". And, as James notes, whether or not you need to suppress the leak depends on whether or not the optimizer does away with the variable. Subtle changes to the code that have nothing to do with memory allocation will appear to add or fix leaks. That is not something I would care to explain or document.
>
> I can see that concern, but this isn’t a battle that we can win: optimizations in general can expose leaks.
>
> IMO, If someone doesn’t want the global to be removed, they should mark it volatile. If they do want it removable, then they can use leak detector features to silence the warning.
>
> > On Apr 20, 2021, at 9:12 AM, Sterling Augustine <saugu...@google.com> wrote:
> >
> > In order to understand how much benefit this change gives to code size, I built clang and related files with and without the patch, both with CMAKE_BUILD_TYPE=Release.
> >
> > clang itself gets about 0.4% smaller (from 145217124 to 144631078)
> > lld gets about 1.85% smaller (from 101129181 to 99243810 bytes)
> >
> > Spot checking a few other random targets, in general, it seems that the benefits depend heavily on the coding style, but roughly, bigger the binary, the less benefit this brings.
> >
> > I suspect that a more aggressive pass as described by Philip Reames could capture a significant part of the benefit without sacrificing functionality. But that would require a more detailed study to be sure.
>
> A ~2% reduction in code size is a huge win. I agree with your comment about it being different with different coding styles. I suspect that this is the sort of thing that will pay particularly for high abstraction code bases.
>
> I don’t see why we would punish general code to make “code that is leaking where formerly not detected, and where users don’t want to mark the root as volatile”. This seems really unprincipled to me, and a slippery slope we can’t go down.
I don't think it's as general or open ended as that - it's a fairly
specific carveout that's been used pretty broadly I think.
So - any interest in a flag to control this behavior, if that's what
it comes to? It's one that a fair bit of software relies on.
- Dave
A sanitizer maintainer has contributed a LeakSanitizer patch to ensure
we don't regress (https://reviews.llvm.org/D100906).
(The test can test the false positive under valgrind which would be
introduced by the original GlobalOpt patch (D69428) as well.)
Just few days ago, I used this pattern to suppress a leak in the in-tree
project LLDB. (https://reviews.llvm.org/D100806).
To bring back some potentially lost optimization, we can try making the
GlobalOpt heuristic smarter, e.g. recognize function pointer types
(as I suggested in the very first few comments on D69428).
Then there is also Philip's suggestion to improve global variable SROA.
A simple code removal does not pull its weight and can cause large
friction to various downstream projects.
My 2 cents:
From: Sterling Augustine via llvm-dev
Sent: 23 апреля 2021 г. 3:44
To: Chris Lattner
Cc: llvm-dev
Subject: [EXTERNAL] Re: [llvm-dev] Eliminating global memory roots (or not) to help leak checkers
> On Apr 19, 2021, at 5:24 AM, James Y Knight <jykn...@google.com> wrote:
>
> There is no problem (no leaks) in the code that users wrote, so adding code annotations (sanitizer suppression file, or attributes) is not a good solution to this issue. The problem is that this optimization introduces a "leak" (from the point of view of the leak checker), which wasn't there before. And in practice, this seems to cause a large number of false positives.
I think that “from the point of view of the leak checker” is the key thing there.
Code that this triggers *is* leaking memory
It was just silenced because the leak was spuriously reachable from a global. Global variables aren’t a preferred way to silence leak detectors, they have other ways to do so :)
> On Apr 19, 2021, at 4:52 PM, Sterling Augustine <saugu...@google.com> wrote:
>
> There may be other ways to disable leak checkers, but they put a burden on users that was not there before. Further, users who try leak checking with and without optimization will get different answers. The bug report will read: "clang at -O2 makes my program leak". And, as James notes, whether or not you need to suppress the leak depends on whether or not the optimizer does away with the variable. Subtle changes to the code that have nothing to do with memory allocation will appear to add or fix leaks. That is not something I would care to explain or document.
I can see that concern, but this isn’t a battle that we can win: optimizations in general can expose leaks.
IMO, If someone doesn’t want the global to be removed, they should mark it volatile. If they do want it removable, then they can use leak detector features to silence the warning.
> On Apr 20, 2021, at 9:12 AM, Sterling Augustine <saugu...@google.com> wrote:
>
> In order to understand how much benefit this change gives to code size, I built clang and related files with and without the patch, both with CMAKE_BUILD_TYPE=Release.
>
> clang itself gets about 0.4% smaller (from 145217124 to 144631078)
> lld gets about 1.85% smaller (from 101129181 to 99243810 bytes)
>
> Spot checking a few other random targets, in general, it seems that the benefits depend heavily on the coding style, but roughly, bigger the binary, the less benefit this brings.
>
> I suspect that a more aggressive pass as described by Philip Reames could capture a significant part of the benefit without sacrificing functionality. But that would require a more detailed study to be sure.
A ~2% reduction in code size is a huge win. I agree with your comment about it being different with different coding styles. I suspect that this is the sort of thing that will pay particularly for high abstraction code bases.
I don’t see why we would punish general code to make “code that is leaking where formerly not detected, and where users don’t want to mark the root as volatile”. This seems really unprincipled to me, and a slippery slope we can’t go down.
On Thu, Apr 22, 2021, 7:28 PM Chris Lattner <clat...@nondot.org> wrote:
> On Apr 19, 2021, at 5:24 AM, James Y Knight <jykn...@google.com> wrote:
>
> There is no problem (no leaks) in the code that users wrote, so adding code annotations (sanitizer suppression file, or attributes) is not a good solution to this issue. The problem is that this optimization introduces a "leak" (from the point of view of the leak checker), which wasn't there before. And in practice, this seems to cause a large number of false positives.
I think that “from the point of view of the leak checker” is the key thing there.
Code that this triggers *is* leaking memory
No, you've got it exactly backwards. "From the point of view of the leak checker", there is a leak, but in actually, there is not.
I'm afraid you're still arguing from mistaken assumptions. As I've already mentioned, reachable memory at program exit is not a leak. That's the definition of "leak" which is always used by leak checkers. (This is not anything new, it's been how leak checkers work for decades, and how they must work.)
Therefore, C++ code that allocates memory and assigns it to a global is not a leak, and it's _still_ not a leak even if it so happens in some instantiation of the program that all of the users of the global have been removed by the optimizer.
The code is correct and it's not leaking memory, but with this change, the leak checker is unable to determine that.
I want to object here. :)
A program with dynamic allocation which has not been reclaimed by
program termination does have a leak. It simply happens to be a
leak that we've chosen by convention to not treat as interesting.
This is a reasonable convention because standard process tear
mechanisms will deallocate it for most classes of memory. The
program could be converted to one which actually doesn't leak by
using static destructors to free the pointed to object.
Just to be clear, this objection is purely on terminology. I think it's important to distinguish between programs which leak (e.g. don't reclaim all memory), and programs which simply aren't interesting from a leak detection standpoint (because the memory is about to be reclaimed anyways.)
Separately from the terminology point above, I'll share my own weakly held opinion from reading along with this thread.
I have generally found the arguments against optimizing away
globals to avoid leak reports unconvincing. The results on the
optimization benefit are clearly worthwhile. If forced to chose
at this moment, I'd trade the optimization impact for the leak
detection usage complexity. To me, it is critical to note that
there are multiple source level changes possible to address the
(true) leaks reported, several of which have already been
suggested in this thread. It's also important to note that we
have other optimizations already in tree which require the same
type of source change.
I would suggest that if the advocates for leak suppression in the
compiler continue to want to argue this point that the burden of
work needs to shift. In particular, I would really like to see
some proactive efforts to either a) assess the optimization
potential tradeoff of an SROA-ish approach, or b) proposals for
making the desired preservation well defined in IR. (i.e. a set
of rules which describe which optimizations are legal - the
current code does not do this!)
It was just silenced because the leak was spuriously reachable from a global. Global variables aren’t a preferred way to silence leak detectors, they have other ways to do so :)
Memory reachable from a global is not a spurious reachability, it is actual reachability. And, the purpose of assigning a value to a global variable in the source code isn't to silence the leak checker, it is to make the object accessible to other code. (People writing code normally aren't and shouldn't be thinking about leak checking.)
> On Apr 19, 2021, at 4:52 PM, Sterling Augustine <saugu...@google.com> wrote:
>
> There may be other ways to disable leak checkers, but they put a burden on users that was not there before. Further, users who try leak checking with and without optimization will get different answers. The bug report will read: "clang at -O2 makes my program leak". And, as James notes, whether or not you need to suppress the leak depends on whether or not the optimizer does away with the variable. Subtle changes to the code that have nothing to do with memory allocation will appear to add or fix leaks. That is not something I would care to explain or document.
I can see that concern, but this isn’t a battle that we can win: optimizations in general can expose leaks.
The word "expose" is invalid here -- that implies that the code is buggy but that the leak checker was previously unable to detect the bug, and now does. But that is not the case at hand. You maybe could say, instead "I can see that concern, but this isn’t a battle that we can win: optimizations in general can cause random false positives in the leak checker." (But, in practice it was pretty much "won" for the last 9 years.)
IMO, If someone doesn’t want the global to be removed, they should mark it volatile. If they do want it removable, then they can use leak detector features to silence the warning.
> On Apr 20, 2021, at 9:12 AM, Sterling Augustine <saugu...@google.com> wrote:
>
> In order to understand how much benefit this change gives to code size, I built clang and related files with and without the patch, both with CMAKE_BUILD_TYPE=Release.
>
> clang itself gets about 0.4% smaller (from 145217124 to 144631078)
> lld gets about 1.85% smaller (from 101129181 to 99243810 bytes)
>
> Spot checking a few other random targets, in general, it seems that the benefits depend heavily on the coding style, but roughly, bigger the binary, the less benefit this brings.
>
> I suspect that a more aggressive pass as described by Philip Reames could capture a significant part of the benefit without sacrificing functionality. But that would require a more detailed study to be sure.
A ~2% reduction in code size is a huge win. I agree with your comment about it being different with different coding styles. I suspect that this is the sort of thing that will pay particularly for high abstraction code bases.
I don’t see why we would punish general code to make “code that is leaking where formerly not detected, and where users don’t want to mark the root as volatile”. This seems really unprincipled to me, and a slippery slope we can’t go down.
In the way you have restated the issue here, there is no benefit to the current behavior, but that's only because of the mistaken assumptions. You have redefined "leak", and are assuming that the problem is buggy software, whose users are upset that valid bugs are found which were not previously found. But that's simply not the case we're dealing with. The code is correct (non-leaking), and it's a regression in leak checker functionality if we start forcing users to add manual annotations as a workaround.
I don't know what the right thing to do here is. But I'm quite sure we cannot arrive at a good decision until everyone can at least get on the same page about what the purpose of a leak checker is. I would hope that there's a path that makes everyone satisfied, but if not, the disagreement needs to be based on relative priority of use cases and engineering trade-offs, not whether the problem EXISTS.
The optimization we see with D69428 is all due to `STATISTIC(...)`
variables (there are ~1000).
llvm::NoopStatistic has 3 unused global pointers. With
https://reviews.llvm.org/D101211 , all the `STATISTIC(...)` contribute
zero size. I don't see D69428 removes any global variable which should
be dropped.
D69428 would drop two global variables which should be retained,
but that is usage issue. I've sent https://reviews.llvm.org/D101217 to fix them.
So at least for Clang, we don't gain any size improvement from D69428.
BTW, it is possible that much of D69428's size gain can be provided by
linker garbage collection(ELF)/dead stripping(Mach-O)/"eliminates
functions and data that are never referenced" (link.exe).
So in general projects, I expect its gain to be tiny.
D69428 and the thread does raise much to improve. e.g. I suspect with
D69428 there are still some `STATISTIC(...)` not optimized out. There
are definitely optimization/code cleanup/test improvement opportunities there.
>>> > clang itself gets about 0.4% smaller (from 145217124 to 144631078)
>>> > lld gets about 1.85% smaller (from 101129181 to 99243810 bytes)
>> LLVM Developers mailing listllvm-dev@lists.llvm.orghttps://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Code that this triggers *is* leaking memory, it was just silenced because the leak was spuriously reachable from a global. Global variables aren’t a preferred way to silence leak detectors, they have other ways to do so :)
"spuriously" reachable is quite questionable here. This way of writing
code is to make the allocation quite intentionally reachable from a
global.
For instance, one of the ways to disable global destruction: (
https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
)
"If all else fails, you can create an object dynamically and never
delete it by using a function-local static pointer or reference (e.g.,
static const auto& impl = *new T(args...);)."
(all else fails in a large enough codebase rather often... )
On Apr 23, 2021, at 7:18 AM, James Y Knight <jykn...@google.com> wrote:That's the definition of "leak" which is always used by leak checkers. (This is not anything new, it's been how leak checkers work for decades, and how they must work.)Therefore, C++ code that allocates memory and assigns it to a global is not a leak, and it's _still_ not a leak even if it so happens in some instantiation of the program that all of the users of the global have been removed by the optimizer.