print sp只显示地址是因为GDB默认仅展示shared_ptr的两个内部指针字段(_M_ptr和_M_refcount),不自动解引用或调用operator*;需手动print *sp或print *sp._M_ptr查看所指对象内容。

直接用 print 看不到对象内容,得手动解引用或展开控制块
为什么 print sp 只显示地址
GDB 默认只读取 shared_ptr 的内存布局:两个指针字段(_M_ptr 和 _M_refcount 或 __ptr_/__cntrl_),不会自动调用 operator* 或展开所指对象。你看到的 0x7fff... 是裸地址,不是对象值。
常见错误现象:print sp 输出类似 {_M_ptr = 0x416ec0, _M_refcount = {...}},点不开、看不到 *sp 的值。
- Linux/macOS 上 GCC + libstdc++:字段名通常是
_M_ptr和_M_refcount - Clang + libc++:字段名可能是
__ptr_和__cntrl_,需用print sp.__ptr_查地址 - 若编译时加了
-fno-rtti,GDB 无法识别类型,print *sp会报错 “no type info”
怎么安全地打印 shared_ptr 指向的对象
最可靠的方式是显式解引用,前提是 _M_ptr 非空且类型可识别:
-
print *sp—— 直接解引用,适用于调试符号完整、类型未被优化掉的情况 -
print *(int*)sp._M_ptr—— 强制按int*解引用(需确认实际类型) -
print *(sp._M_ptr)—— 更稳妥的括号写法,避免运算符优先级问题 - 如果
sp是shared_ptr<myclass></myclass>,且类定义在当前上下文可见,print *sp通常能显示成员变量
注意:print *sp 在 GDB 8.2+ 中基本可用;旧版本可能需先 set print pretty on 并加载 libstdc++ pretty printer。
GDB 查看 control block 里的 use_count
引用计数不在 shared_ptr 实例里,而在它指向的控制块中。字段名和偏移因标准库实现而异:
- libstdc++(GCC):
sp._M_refcount._M_pi->_M_use_count(_M_use_count是原子整型,GDB 可读) - libc++(Clang):
*(sp.__cntrl_)->__shared_weak_owners_ + 1(这是弱引用计数+1,近似 use_count) - 更通用的 fallback:
print sp._M_refcount._M_pi先确认控制块地址,再x/2wd &((...*)_M_pi)->_M_use_count查内存
不建议依赖 sp.use_count():GDB 7.12 以前不支持内联函数调用,且该函数本身有调试器副作用——暂停瞬间的快照值可能被其他线程改写。
容易被忽略的关键点
真正难的不是“怎么打出来”,而是“打出来的值是否可信”:
- 多线程下
use_count()或控制块字段的值只是断点时刻快照,不能用于逻辑判断(比如if (sp.use_count() == 1)) - 移动构造或
std::move后,原shared_ptr变为空,_M_ptr为nullptr,强行print *sp会触发 GDB 错误或 SIGSEGV - Release 编译(
-O2 -g)下,部分字段可能被优化掉,print sp._M_ptr显示 “optimized out”,此时只能靠info registers或汇编级调试


















