On which platform is func (shared_ptr (...), shared_ptr (...)) really dangerous?

I remember that Scott Myers taught me that

func(shared_ptr(new P), shared_ptr(new Q)); 

is dangerous because (if I remember correctly) the order of memory allocation, link counting (building), and assigning functional parameters allows a leak (theoretically?) to occur in rare cases. To prevent this, encapsulate shared_ptr in a function call, for example. in make_shared() .

 func(make_shared<P>(), make_shared<Q>()); 

Here is some discussion about this too.

I would like to know if there are (current) compilers in the field , on some systems , which can actually leave some hole in some cases of errors? Or were those days gone, or were they just theoretical?

The most interesting thing will be to know if any of these problems have:

  • g ++ 4.x or g ++ 2.95, on Linux i386, x64, ARM, m68k or any Windows
  • Visual C ++ on i368, x64 or ARM
  • Clang / LLVM for Linux or any of its platforms
  • What about C ++ compilers to / from Sun or IBM, HP-UX?

Has anyone watched this behavior on their particular platform?

+4
source share
4 answers
 func(shared_ptr(new P), shared_ptr(new Q)); 

The C ++ compiler can implement this in the following order:

  • new Q
  • new P
  • build shared_ptr around selected P
  • build shared_ptr around selected Q
  • func call

(The compiler can execute 1, 2, 3, and 4 in any order if 1 to 4 and 2 to 3).

In the above order, if the constructor is P or the call is new throws, Q is a memory leak (memory allocated, but shared_ptr has not yet been built around it).

So you have to call std::make_shared (which handles the exceptions in the distribution correctly), and you know that when std::make_shared returned for one of them, shared_ptr fully constructed and will not leak.

I would like to know if there are (current) compilers in the field, on some systems that can really leave some hole in some cases of error?

All standards-compliant compilers will have this behavior.

0
source

This is not a platform issue, it is an exception security issue. So the answer to your real question is: all of these platforms can identify the problem.

A memory leak problem occurs due to two things:

  • Allocating memory with new can cause bad_alloc
  • The order in which the function arguments are calculated is not specified.

Docs for boost::shared_ptr will easily catch it here

A detailed description of the treatment of a common problem here (GOTW) is more

The reason this may be "rare" arises because it is actually not normal to get bad_alloc , but your code should safely handle this feature if necessary to prevent memory leaks.

(I can say "I can" show this - I did not check that they all throw bad_alloc if new fails ...)

+4
source

since the new operations are performed first, and then they are passed to the shared_ptr constructor, but the shared_ptr construct is not defined at first, so one of the newly created objects may cause a memory leak.

0
source

This is unsafe on any platform that has a reordering optimizer if this optimizer performs the following optimizations A;B;A;B => A;A;B;B This optimization improves cache efficiency, so overall it's a good idea.

Obviously, the optimizer can only reorder B and A if their relative order is not specified, which happens here.

0
source

Source: https://habr.com/ru/post/1495479/


All Articles