C++11 標準long
では、オブザーバー関数の戻り値の型として指定されていますが、実装が共有所有権use_count()
までサポートする必要があるかどうかは明示的に指定されていません。2^(sizeof(long)*8-1)-1
また、参照カウンターがオーバーフローしたときに何が起こるかも指定されていません。
実装 (例: boost::shared_ptr
Fedora 23、x86-64 では 1.58) は内部で 32 ビット カウンターを使用し、オーバーフローをチェックしません。
つまり、次のことを意味します。
- 最大参照カウントは
2^31-1
です。
- オーバーフローして所有権を解放すると、使用後の解放の問題が発生する可能性があります
ブーストはプラットフォームごとに異なる低レベルの特殊化を使用するため、ブレークポイントを設定することで詳細を確認できます*add_ref_lock
。Fedora 23/x86-64 では、ここで停止します。
/usr/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
[..]
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
[..]
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
以下も参照してください。
GNU STL (libstdc++) の shared_pointer 実装は、Boost 1.32 のものに基づいており、この問題 (Fedora 23/x86-64 で) もあり、_Atomic_word
型は参照カウントに使用されます。また、これは 32 ビットのみであり、オーバーフローはチェックされません。
対照的に、LLVM の libc++shared_ptr
実装はlong
参照カウンターとして使用します。つまり、x86-64 のような LP64 プラットフォームでは、所有者までの間でオブジェクトを共有できます2^63-1
。