- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There seems to be quite a serious issue with std::weak_ptr<> and Intel Compiler 19.0 and 19.1 with Visual Studio 2019.
The problem appears to be that the class _Ref_count_base, which includes the code
_Atomic_counter_t _Uses = 1;
_Atomic_counter_t _Weaks = 1;
Does not appear to be initializing _Weaks to 1 ( when using Intel, not MSVC)
Run this simple program under the debugger and examine the values of _Weaks after the std::weak_ptr<int> has been constructed
Compiled with MSVC and with Intel. Debug at the return statement. You will see _Weaks=2 with MSVC but _Weaks=1 with Intel
int main()
{
std::shared_ptr<int> aStrong = std::make_shared<int>(10);
std::weak_ptr<int> aWeak(aStrong);
return 0;
}
- Tags:
- Bug
- CC++
- Development Tools
- Intel® C++ Compiler
- Intel® Parallel Studio XE
- Intel® System Studio
- Optimization
- Parallel Computing
- Vectorization
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Example of how dangerous this is - the shared_ptr points to garbage after the weak_ptr goes out of scope.
What is happening is that since the weak_ptr _Weaks is initialized to 0 (not 1), the weak_ptr goes out of scope, the _Weaks field is decremented to 0. This causes the base class _Ref_count_base to call _Delete_this() which deletes the structure shared by the std::shared_ptr<> and the std::weak_ptr<>. So when the std::shared_ptr<> is dereferenced it goes to find the pointer to the aTest object, it gets garbage from deleted memory.
#include <memory>
#include <iostream>
class atest
{
public:
atest(int n):n_(n) {};
virtual ~atest()
{
std::cout << "calling destructor" << std::endl;
}
int n_;
};
int main()
{
std::shared_ptr<atest> aStrong = std::make_shared<atest>(10);
{
std::weak_ptr<atest> aWeak(aStrong);
}
std::cout << "should be 10: " << aStrong->n_ << std::endl;
return 0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This may not have been encountered before as in previous versions of <memory> ( some versions prior to 16.4.4 Visual Studio 2019 version), the code looked like this
_Atomic_counter_t _Uses;
_Atomic_counter_t _Weaks;
protected:
_Ref_count_base()
: _Uses(1), _Weaks(1) // non-atomic initializations
{}
Now, it looks like this
_Atomic_counter_t _Uses = 1;
_Atomic_counter_t _Weaks = 1;
protected:
constexpr _Ref_count_base() noexcept = default; // non-atomic initializations
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
And to add insult to injury... even if you don't use weak_ptr<> then this bug will cause every single std::shared_ptr<> to a unique object to now leak an amount of memory equal to the sizeof() the _Ref_count_base (and derived) object.
Why? When a shared_ptr<> is destroyed it decrements _Uses and checks the _Uses count. If that is 0, the pointed-to-object is destroyed.So far, so good...
It then decrements _Weaks and checks if the _Weaks count==0. Sadly, this count will be -1 ( assuming no weak_ptr<>s) , not 0 so the _Ref_count_base will not call _Delete_this which deallocates the _Ref_count_base and derived objects.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is the same bug as described in https://software.intel.com/en-us/forums/intel-c-compiler/topic/827586
And it STILL has not been fixed in 2020?
I see the problem is Release mode, not just Debug mode.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
We have verified this on Linux with icc/icpc version 19.1. We did not notice any issue. We are in the process of verifying this on Visual studio environment. We will get back to you once its done.
-Rahul
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Vaidya, Rahul (Intel) wrote:Hi,
We have verified this on Linux with icc/icpc version 19.1. We did not notice any issue. We are in the process of verifying this on Visual studio environment. We will get back to you once its done.
-Rahul
Why are you wasting your time on Linux? There is no problem on Linux as the STL headers are different. This is ONLY a problem under Visual Studio 2019.
Andrew
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The "workaround" is to edit <memory> in Visual Studio and change the code.
//constexpr _Ref_count_base() noexcept = default; // non-atomic initializations
_Ref_count_base():_Uses(1),_Weaks(1)
{
} // non-atomic initializations
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Intel Support ticket #04526637
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for letting us know the ticket number. Our Engineer will work on it and then updates the ticket with new finding/info.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This bug means Intel Compiler 2020 cannot be with Visual Studio 2019 16.4.x to compile any C++ code uses std::weak_ptr<> and std::shared_ptr<> ( without hacking the <memory> header) . I would categorize that as a "show-stopper".
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This bug has been fixed in 2020 Update 1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This issue has been resolved and we will no longer respond to this thread. If you require additional assistance from Intel, please start a new thread. Any further interaction in this thread will be considered community only.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page