In a naive reference-counting smart pointer implementation, the reference-counter could overflow. How is this overflow avoided or handled in C++ standard library implementations?
Asked
Active
Viewed 608 times
8

curiousguy
- 8,038
- 2
- 40
- 58

sergej
- 17,147
- 6
- 52
- 89
-
8I'm not sure you could overflow the reference count. If they used `size_t` then they should not be able to allocate enough pointers to overflow that. – NathanOliver May 22 '17 at 14:43
-
4`std::shared_ptr`'s function to return the reference counter [returns a `long`](http://en.cppreference.com/w/cpp/memory/shared_ptr/use_count), so I guess that is the "soft" limit. – Rakete1111 May 22 '17 at 14:45
-
2You could always read the code. – Donnie May 22 '17 at 14:48
-
8That's a real concern. If you generate a new reference every nanosecond, you would overflow a 64-bit count in less than 600 years. – stark May 22 '17 at 14:51
-
4@stark and your pointers would consume more memory than can be addressed by a 64 bit pointer :) – eerorika May 22 '17 at 14:52
-
If you could overflow it, it would be undefined behavior on account of signed overflow. It's handled by assuming there won't be more than `std::numeric_limits
::max` references (at least that's what libstdc++ does). – AndyG May 22 '17 at 14:55 -
4@stark [`long` is not 64-bit on all platforms](https://software.intel.com/en-us/articles/size-of-long-integer-type-on-different-architecture-and-os), even if you compile for 64-bit. – zett42 May 22 '17 at 14:58
-
@stark: Also "less than 300 years" is a tighter bound [source](https://wandbox.org/permlink/vd2LZv96mR69uT1f). Edit: You must have assumed unsigned, which is a false assumption. – AndyG May 22 '17 at 15:03
-
6If your program overflows a reference counter, you probably deserve it. – n. m. could be an AI May 22 '17 at 15:19
-
related: a WG issue [directly referenced implementing shared_ptr using reflinking](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2434) when changing the wording for use_count. I'm unsure that the resolved issue implies that it is still valid to implement it as such. Theoretically, such an implementation wouldn't overflow. – Rusty Shackleford May 23 '17 at 01:14
-
1@Donnie "_You could always read the code_" You can always assume the original poster wants an answer that is not tied a particular version of a particular compiler. – curiousguy Jun 01 '17 at 16:52
-
@curiousguy - Well, if it's not in the standard (it's not), then the only answer is one that is tied to a particular compiler or implementation. I may have came across as snitty, but it seems a lot of people don't realize that the standard library is at hand and readable. – Donnie Jun 02 '17 at 22:13
1 Answers
6
Snippets from stdlibc++ headers:
typedef int _Atomic_word;
class _Sp_counted_base
/*snip*/
_Atomic_word _M_use_count;
/*snip*/
_M_weak_add_ref()
{ __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
/*snip*/
__atomic_add_dispatch(/*snip*/)
{
/*snip*/
__atomic_add_single(/*snip*/);
/*snip*/
}
__atomic_add_single(/*snip*/)
{ *__mem += __val; }
Conclusion: This particular implementation "handles" reference-counter overflow by ignoring the possibility.

eerorika
- 232,697
- 12
- 197
- 326
-
It is surprising that they use an `int` but I is hard, for me at least, to envision a use case for 32767 pointers to the same thing. – NathanOliver May 22 '17 at 15:12
-
2In general yes, but what if an attacker manages to produce some malicious input that causes the program to create them? – Bob Jansen May 22 '17 at 15:24
-
6@BobJansen that could be bad. Another conclusion: You should not let user input directly affect the number of shared pointers without a bound. In fact, I would extend this to anything that allocates memory (or other resources). – eerorika May 22 '17 at 15:29
-
2I just had a look at the MSVC++2017 implementation of `std::shared_ptr`. They call [`_InterlockedIncrement()`](https://learn.microsoft.com/en-us/cpp/intrinsics/interlockedincrement-intrinsic-functions) which overflows aswell. – zett42 May 22 '17 at 19:02