Re: 关于boost memory 2.20

14 views
Skip to first unread message

shiwei xu

unread,
Dec 10, 2008, 9:13:20 AM12/10/08
to Yingfeng Zhang, std...@googlegroups.com
1. 关于 winx_call ,这是一个疏漏。不应该有宏。感谢反馈。
2. _alloca 在某些平台下不存在,我会检测并将其定义为 alloca,我有些奇怪在你那有这个问题,我要确认下。
3. 内存泄漏是错误的检测结果,应当忽略。事实上 auto_alloc 和 scoped_alloc 的代码是相同的,只有策略层面的不同。
4. 关于boost memory应该把所有代码都放入头文件:简单说能够放入头文件的我都已经放入了。不能放的是那些"singleton"模式的对象,必须放入到.so/.dll中。
    关于动态库(.so/.dll)依赖,规则是这样的:
    1) 使用 auto_alloc 不需要 link 动态库。
    2) 使用 scoped_alloc 有时需要 link 动态库。如:
           scoped_alloc alloc;
           ...
         但是,如果你把它改为:
           block_pool recycle;
           scoped_alloc alloc(recycle);
           ...
         那么,我们就不需要 link 动态库了。原因在于 scoped_alloc alloc; 这个定义等价于:
           scoped_alloc alloc(tls_block_pool::instance());
           ...
         tls_block_pool::instance() 是一个 block_pool 的 singleton 对象,它必须出现于动态库中。
         这也是为什么 boost memory 需要一个动态库(但多数情况下用不上)。
5. 抱歉,Mac OS X 没有尝试编译过。个人暂没有这样的环境,不过我将尝试进行这一步工作。
2008/12/10 Yingfeng Zhang <yingfen...@gmail.com>
你好
我准备在项目中引入你的boost memory 2.20 但刚开始测试就发现一些问题,我的环境是linux 内核 2.6.10 +gcc 4.1
首先是编译错误 boost/memory/memory.hpp

inline void winx_call swap(void* a, void* b, size_t cb)
{
    void* t = _alloca(cb);
    memcpy(t, a, cb);
    memcpy(a, b, cb);
    memcpy(b, t, cb);
}

template <class Type>
void winx_call swap_object(Type* a, Type* b) {
    swap(a, b, sizeof(Type));
}

只有把winx_call和_alloca 去掉才可以:
inline void swap(void* a, void* b, size_t cb)
{
    void* t = alloca(cb);
    memcpy(t, a, cb);
    memcpy(a, b, cb);
    memcpy(b, t, cb);
}

template <class Type>
void  swap_object(Type* a, Type* b) {
    swap(a, b, sizeof(Type));
}

其次,我使用了你提供的stl_containers.cpp进行测试,但用valgrind发觉很大内存漏洞:



==9386== Memcheck, a memory error detector.
==9386== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==9386== Using LibVEX rev 1732, a library for dynamic binary translation.
==9386== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==9386== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==9386== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==9386== For more details, rerun with: -v
==9386==

===== Deque (scoped_alloc) =====

===== List (scoped_alloc) =====

===== Set (scoped_alloc) =====

===== Map (scoped_alloc) =====
==9386==
==9386== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==9386== malloc/free: in use at exit: 10,890,496 bytes in 670 blocks.
==9386== malloc/free: 670 allocs, 0 frees, 10,890,496 bytes allocated.
==9386== For counts of detected errors, rerun with: -v
==9386== searching for pointers to 670 not-freed blocks.
==9386== checked 3,393,752 bytes.
==9386==
==9386== 16 bytes in 1 blocks are definitely lost in loss record 1 of 7
==9386==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9386==    by 0x400FC1: testMap() (tls.hpp:137)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386==
==9386== 441,520 (16 direct, 441,504 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 7
==9386==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9386==    by 0x40196A: testDeque() (tls.hpp:137)
==9386==    by 0x401A48: testStlContainers() (test.cc:84)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386==
==9386== 2,403,760 (16 direct, 2,403,744 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 7
==9386==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9386==    by 0x4016CC: testList() (tls.hpp:137)
==9386==    by 0x401A4D: testStlContainers() (test.cc:85)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386==
==9386== 4,022,608 (16 direct, 4,022,592 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 7
==9386==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9386==    by 0x4011D0: testSet() (tls.hpp:137)
==9386==    by 0x401A52: testStlContainers() (test.cc:86)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386==
==9386== 16,352 bytes in 1 blocks are possibly lost in loss record 5 of 7
==9386==    at 0x4A059F6: malloc (vg_replace_malloc.c:149)
==9386==    by 0x4C09F88: boost::memory::stdlib_alloc::allocate(unsigned long) (system_alloc.hpp:67)
==9386==    by 0x4C0A033: boost::memory::system_pool_imp<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:141)
==9386==    by 0x4C0A059: boost::memory::system_pool_s<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:181)
==9386==    by 0x4C09BE0: _boost_SystemPoolAlloc (system_pool.cpp:24)
==9386==    by 0x400FF3: testMap() (system_alloc.hpp:139)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386==
==9386== 4,006,240 bytes in 245 blocks are still reachable in loss record 6 of 7
==9386==    at 0x4A059F6: malloc (vg_replace_malloc.c:149)
==9386==    by 0x4C09F88: boost::memory::stdlib_alloc::allocate(unsigned long) (system_alloc.hpp:67)
==9386==    by 0x4C0A033: boost::memory::system_pool_imp<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:141)
==9386==    by 0x4C0A059: boost::memory::system_pool_s<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:181)
==9386==    by 0x4C09BE0: _boost_SystemPoolAlloc (system_pool.cpp:24)
==9386==    by 0x4022CE: std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, boost::memory::stl_allocator<std::pair<int const, int>, boost::memory::region_alloc<boost::memory::policy::pool> > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<int const, int> const&) (system_alloc.hpp:139)
==9386==    by 0x402377: std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, boost::memory::stl_allocator<std::pair<int const, int>, boost::memory::region_alloc<boost::memory::policy::pool> > >::insert_unique(std::pair<int const, int> const&) (stl_tree.h:931)
==9386==    by 0x400EEA: testMap() (stl_map.h:396)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386==
==9386== 6,867,840 bytes in 420 blocks are indirectly lost in loss record 7 of 7
==9386==    at 0x4A059F6: malloc (vg_replace_malloc.c:149)
==9386==    by 0x4C09F88: boost::memory::stdlib_alloc::allocate(unsigned long) (system_alloc.hpp:67)
==9386==    by 0x4C0A033: boost::memory::system_pool_imp<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:141)
==9386==    by 0x4C0A059: boost::memory::system_pool_s<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:181)
==9386==    by 0x4C09BE0: _boost_SystemPoolAlloc (system_pool.cpp:24)
==9386==    by 0x40199C: testDeque() (system_alloc.hpp:139)
==9386==    by 0x401A48: testStlContainers() (test.cc:84)
==9386==    by 0x401A68: main (test.cc:92)
==9386==
==9386== LEAK SUMMARY:
==9386==    definitely lost: 64 bytes in 4 blocks.
==9386==    indirectly lost: 6,867,840 bytes in 420 blocks.
==9386==      possibly lost: 16,352 bytes in 1 blocks.
==9386==    still reachable: 4,006,240 bytes in 245 blocks.
==9386==         suppressed: 0 bytes in 0 blocks.
[newpeak@localhost stdext-2.2.00]$ valgrind --tool=memcheck --show-reachable=yes --leak-check=full ./main  >1.txt
==9423== Memcheck, a memory error detector.
==9423== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==9423== Using LibVEX rev 1732, a library for dynamic binary translation.
==9423== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==9423== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==9423== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==9423== For more details, rerun with: -v
==9423==
==9423==
==9423== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==9423== malloc/free: in use at exit: 10,890,496 bytes in 670 blocks.
==9423== malloc/free: 670 allocs, 0 frees, 10,890,496 bytes allocated.
==9423== For counts of detected errors, rerun with: -v
==9423== searching for pointers to 670 not-freed blocks.
==9423== checked 3,393,752 bytes.
==9423==
==9423== 16 bytes in 1 blocks are definitely lost in loss record 1 of 7
==9423==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9423==    by 0x400FC1: testMap() (tls.hpp:137)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423==
==9423== 441,520 (16 direct, 441,504 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 7
==9423==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9423==    by 0x40196A: testDeque() (tls.hpp:137)
==9423==    by 0x401A48: testStlContainers() (test.cc:84)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423==
==9423== 2,403,760 (16 direct, 2,403,744 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 7
==9423==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9423==    by 0x4016CC: testList() (tls.hpp:137)
==9423==    by 0x401A4D: testStlContainers() (test.cc:85)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423==
==9423== 4,022,608 (16 direct, 4,022,592 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 7
==9423==    at 0x4A06205: operator new(unsigned long) (vg_replace_malloc.c:167)
==9423==    by 0x4011D0: testSet() (tls.hpp:137)
==9423==    by 0x401A52: testStlContainers() (test.cc:86)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423==
==9423== 16,352 bytes in 1 blocks are possibly lost in loss record 5 of 7
==9423==    at 0x4A059F6: malloc (vg_replace_malloc.c:149)
==9423==    by 0x4C09F88: boost::memory::stdlib_alloc::allocate(unsigned long) (system_alloc.hpp:67)
==9423==    by 0x4C0A033: boost::memory::system_pool_imp<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:141)
==9423==    by 0x4C0A059: boost::memory::system_pool_s<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:181)
==9423==    by 0x4C09BE0: _boost_SystemPoolAlloc (system_pool.cpp:24)
==9423==    by 0x400FF3: testMap() (system_alloc.hpp:139)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423==
==9423== 4,006,240 bytes in 245 blocks are still reachable in loss record 6 of 7
==9423==    at 0x4A059F6: malloc (vg_replace_malloc.c:149)
==9423==    by 0x4C09F88: boost::memory::stdlib_alloc::allocate(unsigned long) (system_alloc.hpp:67)
==9423==    by 0x4C0A033: boost::memory::system_pool_imp<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:141)
==9423==    by 0x4C0A059: boost::memory::system_pool_s<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:181)
==9423==    by 0x4C09BE0: _boost_SystemPoolAlloc (system_pool.cpp:24)
==9423==    by 0x4022CE: std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, boost::memory::stl_allocator<std::pair<int const, int>, boost::memory::region_alloc<boost::memory::policy::pool> > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<int const, int> const&) (system_alloc.hpp:139)
==9423==    by 0x402377: std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, boost::memory::stl_allocator<std::pair<int const, int>, boost::memory::region_alloc<boost::memory::policy::pool> > >::insert_unique(std::pair<int const, int> const&) (stl_tree.h:931)
==9423==    by 0x400EEA: testMap() (stl_map.h:396)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423==
==9423== 6,867,840 bytes in 420 blocks are indirectly lost in loss record 7 of 7
==9423==    at 0x4A059F6: malloc (vg_replace_malloc.c:149)
==9423==    by 0x4C09F88: boost::memory::stdlib_alloc::allocate(unsigned long) (system_alloc.hpp:67)
==9423==    by 0x4C0A033: boost::memory::system_pool_imp<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:141)
==9423==    by 0x4C0A059: boost::memory::system_pool_s<boost::memory::policy::stdlib, boost::memory::normal_stack>::allocate(unsigned long) (system_pool.hpp:181)
==9423==    by 0x4C09BE0: _boost_SystemPoolAlloc (system_pool.cpp:24)
==9423==    by 0x40199C: testDeque() (system_alloc.hpp:139)
==9423==    by 0x401A48: testStlContainers() (test.cc:84)
==9423==    by 0x401A68: main (test.cc:92)
==9423==
==9423== LEAK SUMMARY:
==9423==    definitely lost: 64 bytes in 4 blocks.
==9423==    indirectly lost: 6,867,840 bytes in 420 blocks.
==9423==      possibly lost: 16,352 bytes in 1 blocks.
==9423==    still reachable: 4,006,240 bytes in 245 blocks.
==9423==         suppressed: 0 bytes in 0 blocks.

因此在目前看来我是不敢将boost::memory 引入项目的

此外,对boost::memory有个建议,能否把所有实现都放入头文件中?
因为如果它还没有被放到boost库中,那么对于使用者是非常不便的,每台使用该库的程序都要单独编译boost::memory,然后才能供其他程序使用




Best
Yingfeng




shiwei xu

unread,
Dec 10, 2008, 9:39:53 AM12/10/08
to Yingfeng Zhang, std...@googlegroups.com
这种错误我以前也见过,并非真正意义上的内存泄漏。其根本原因仍然在那个 singleton 的 block_pool 上。因为内存释放时被"还"给了这个 block_pool 而没有真正释放。而该 block_pool 在程序退出时释放(其实就算没有释放操作也无所谓了,因为程序正在退出)。
 
另外,说一下,gc_alloc 我觉得还没有考虑得特别清楚,我准备在下一个版本暂时去除之。请忽略这个类。
2008/12/10 Yingfeng Zhang <yingfen...@gmail.com>
你好
关于3 是我的疏忽,auto_alloc和scoped_alloc,在simple_example里是没有内存泄露的,但testGCAlloc和testTlsScopedAlloc确实有泄露,内容在第二封邮件里已有描述
stl_container的相关测试内存确实有泄露
你是说不该相信valgrind的检测结果?

更多反馈会逐渐给出,因为目前在mac 平台上,此前的测试程序都没办法跑了,还在逐条排除中



2008/12/10 shiwei xu <xushi...@gmail.com>

shiwei xu

unread,
Dec 11, 2008, 3:08:43 AM12/11/08
to Yingfeng Zhang, std...@googlegroups.com
用 class tls_block_pool_init 即可。
另外,理论上 tls_block_pool_init 不用也没有关系。boost-memory.so 初始化和反初始化应该也会做类似的事情。
2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>
应当是系统设计问题导致的内存漏洞:
template <class AllocT, class TlsAllocT>
class proxy_alloc
{
private:
    AllocT* m_alloc;
public:
    proxy_alloc() : m_alloc(&TlsAllocT::instance()) {}
}
在这里m_alloc 调用了 TlsAllocT::instance来获得一个block_pool的实例,初次调用应当会new 一个实例对象出来

template <class Unused>
class tls_block_pool_imp
{
private:
    static tls_block_pool_t* _tls_blockPool;
public:
    tls_block_pool_imp() {
//这里没有调用
        _tls_blockPool->init();
    }
    ~tls_block_pool_imp() {
//这里没有调用
        _tls_blockPool->term();
    }

    static block_pool& BOOST_MEMORY_CALL instance()
    {
        return _tls_blockPool->get();
    }
};

在这里, instance方法是静态方法,直接 get() 返回了

tls_block_pool_imp 的构造器和析构函数没有被调用,也就是 _tls_blockPool->term() 没有起到作用,因此 _tls_blockPool->get()生成的对象没有被cleanup

我在上面注释的地方还有tls.hpp里所有可能的地方都加了log,证明了我的判断

这就解释了为什么我把tls_block_pool_t换成block_pool就没有泄露了




2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>

我尝试了一下

你在block_pool中的singleton:
tls_block_pool_t g_tls_blockPool;
如果把它改成
block_pool g_blockPool;
同时tls_block_pool_imp里相应tls_block_pool_t的动作去掉
这样的话,即便采用
boost::scoped_alloc alloc;
根据valgrind也不会有内存泄露了

所以我决定看看是不是tls_object 的实现有问题先





2008/12/10 shiwei xu <xushi...@gmail.com>

shiwei xu

unread,
Dec 11, 2008, 3:10:31 AM12/11/08
to Yingfeng Zhang, std...@googlegroups.com
多谢协助移植 boost memory 到 mac os x。 :)

2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>
Sorry  应当是我的疏忽

class tls_block_pool_init的存在确保了tls对象的正确使用,不过我把它给注释掉了

Btw: 目前我把.cpp文件里的singleton移到了.h文件中,此外还有一些.cpp的依赖给排除,这样尽管全局变量的声明和定义都在一起,但由于这些全局变量并没有放在接口文件memory.hpp中,因此在项目中应当不会被包含多次导致重复定义, 目前看来,似乎可用了。

关于mac os X,主要需要这么几个修改
1  mac os X的malloc.h通常位于 /usr/include/malloc/malloc.h下,而不是 常规的/usr/include/malloc.h,因此要么 include <malloc/malloc.h> ,要么用户手动做一个 ln -s /usr/include/malloc/malloc.h /usr/include/malloc.h
2 pthread.hpp中的GetCurrentThreadId函数,需要 (DWORD)(pthread_self()->__sig); 因为 pthread_self()的返回类型是个指向某个结构的指针
3 system_alloc.hpp中 _msize的定义是malloc_usable_size,这个函数在mac os x下无效,因此暂时用malloc_size来代替
4 basic.hpp中 #pragma pack() 会跟mac os X的系统文件定义重复,在mac 下暂时把这个宏去掉
5 最后一个修改暂时还没进行, 是如果把scoped_alloc应用于std::map时,模板匹配出问题,以后有空再做相关修正。





2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>
2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>






2008/12/10 shiwei xu <xushi...@gmail.com>
这种错误我以前也见过,并非真正意义上的内存泄漏。其根本原因仍然在那个 singleton 的 block_pool 上。因为内存释放时被"还"给了这个 block_pool 而没有真正释放。而该 block_pool 在程序退出时释放(其实就算没有释放操作也无所谓了,因为程序正在退出)。

shiwei xu

unread,
Dec 11, 2008, 3:20:46 AM12/11/08
to Yingfeng Zhang, std...@googlegroups.com
另外提醒下,把 singleton 从 so 移到 .h/.cpp 中是不妥的。
原因在于,如果你的程序有多个模块(指可执行程序或者so)都依赖 boost memory 的话,将导致 singleton 对象有多个实例,其 singleton 的语义就被破坏。
这也是我之前说,singlton的对象必须实现于 so 中的原因。
当然,如果你假设程序只有一个可执行程序,不会有太多的模块,那么也无不会出错,但是我建议不要有这样的假设。
2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>





2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>
2008/12/11 Yingfeng Zhang <yingfen...@gmail.com>






2008/12/10 shiwei xu <xushi...@gmail.com>
这种错误我以前也见过,并非真正意义上的内存泄漏。其根本原因仍然在那个 singleton 的 block_pool 上。因为内存释放时被"还"给了这个 block_pool 而没有真正释放。而该 block_pool 在程序退出时释放(其实就算没有释放操作也无所谓了,因为程序正在退出)。

LI Daobing (李道兵)

unread,
Dec 11, 2008, 3:54:20 AM12/11/08
to std...@googlegroups.com, Yingfeng Zhang
2008/12/11 shiwei xu <xushi...@gmail.com>:

> 另外提醒下,把 singleton 从 so 移到 .h/.cpp 中是不妥的。
> 原因在于,如果你的程序有多个模块(指可执行程序或者so)都依赖 boost memory 的话,将导致 singleton 对象有多个实例,其
> singleton 的语义就被破坏。
> 这也是我之前说,singlton的对象必须实现于 so 中的原因。
> 当然,如果你假设程序只有一个可执行程序,不会有太多的模块,那么也无不会出错,但是我建议不要有这样的假设。

我觉得是没有问题的。

两个模块使用同样的符号,在链接时会合并的,不过可以测试一下, :-)

--
Best Regards,
LI Daobing

shiwei xu

unread,
Dec 11, 2008, 4:02:08 AM12/11/08
to std...@googlegroups.com, Yingfeng Zhang
没测试过。用 dlopen 也会合并吗?
不过,我知道至少 windows 的 dll 是不合并的。so机理上和 dll 不太一样,我至今还不是很清楚 so 的加载过程。
2008/12/11 LI Daobing (李道兵) <lida...@gmail.com>

LI Daobing (李道兵)

unread,
Dec 11, 2008, 4:09:06 AM12/11/08
to std...@googlegroups.com, Yingfeng Zhang
2008/12/11 LI Daobing (李道兵) <lida...@gmail.com>:
测试案例见附件,测试结果如下,最后输出的指针一致,表示可以把 sigleton 写入头文件

$ make
g++ -shared -o b.so b.cpp
g++ -shared -o c.so c.cpp
g++ -o d d.cpp b.so c.so
LD_LIBRARY_PATH=. ./d
a1: 0x9912028, a2: 0x9912028

test.tgz

shiwei xu

unread,
Dec 11, 2008, 4:15:34 AM12/11/08
to std...@googlegroups.com, Yingfeng Zhang
我明白了。
不过这样让我觉得 so 的使用挺"恐怖"。因为它的symbol是全局的。
也就是说,我在so中定义任意一个函数名/全局变量名,都得考虑是否和其他so重名了。
我以前就遇到过这个bug,定义了一个 _X 开头的函数,结果始终没有办法调用到,结果发现调用到 xlib 中去了。
还有一点是,如果你用 dlopen 的话,结果会不同。也就是说,自动链接和 dlopen 的行为是不一致的。

LI Daobing (李道兵)

unread,
Dec 11, 2008, 4:27:55 AM12/11/08
to std...@googlegroups.com, Yingfeng Zhang
2008/12/11 shiwei xu <xushi...@gmail.com>:

> 我明白了。
> 不过这样让我觉得 so 的使用挺"恐怖"。因为它的symbol是全局的。
> 也就是说,我在so中定义任意一个函数名/全局变量名,都得考虑是否和其他so重名了。
> 我以前就遇到过这个bug,定义了一个 _X 开头的函数,结果始终没有办法调用到,结果发现调用到 xlib 中去了。
> 还有一点是,如果你用 dlopen 的话,结果会不同。也就是说,自动链接和 dlopen 的行为是不一致的。

确认 dlopen 结果不同,测试案例见附件。 e 的结果就是 dlopen 的,结果是不一样,链接是没有问题的。

不过我觉得 dlopen 时用户应当自行考虑这个问题。

$ make
g++ -shared -o b.so b.cpp
g++ -shared -o c.so c.cpp
g++ -o d d.cpp b.so c.so

g++ -g -o e e.cpp -ldl
LD_LIBRARY_PATH=. ./d
a1: 0x9896028, a2: 0x9896028
LD_LIBRARY_PATH=. ./e
a1: 0x89093b0
a2: 0x8909758

test.tgz

LI Daobing (李道兵)

unread,
Dec 11, 2008, 4:31:08 AM12/11/08
to std...@googlegroups.com
2008/12/11 shiwei xu <xushi...@gmail.com>:

> 我明白了。
> 不过这样让我觉得 so 的使用挺"恐怖"。因为它的symbol是全局的。
> 也就是说,我在so中定义任意一个函数名/全局变量名,都得考虑是否和其他so重名了。
> 我以前就遇到过这个bug,定义了一个 _X 开头的函数,结果始终没有办法调用到,结果发现调用到 xlib 中去了。
> 还有一点是,如果你用 dlopen 的话,结果会不同。也就是说,自动链接和 dlopen 的行为是不一致的。

一般来讲,设计库的时候会打一个版本戳,可以减少这种问题,比如后面 @@DB4_6 就是版本戳。

这样不仅可以避免你的问题,而且如果你的两个 .so 一个用 db4.5 编译,一个用 db4.6 编译,那么仍然可以同时使用。

$ readelf -a /usr/lib/libdb-4.6.so | grep @@ | head
137: 00078af0 571 FUNC GLOBAL DEFAULT 12
__repmgr_set_local_site@@DB4_6
138: 001121d0 997 FUNC GLOBAL DEFAULT 12 __txn_checkpoint@@DB4_6
139: 0005a5d0 164 FUNC GLOBAL DEFAULT 12 __qam_pgin_out@@DB4_6
140: 000a3ad0 24 FUNC GLOBAL DEFAULT 12 __dbcl_dbc_count_ret@@DB4_6
141: 000d9420 83 FUNC GLOBAL DEFAULT 12 __env_set_tmp_dir@@DB4_6
142: 000c16d0 1738 FUNC GLOBAL DEFAULT 12 __db_open@@DB4_6
143: 000d3f60 935 FUNC GLOBAL DEFAULT 12 __dbreg_register_log@@DB4_6
144: 000a3a50 34 FUNC GLOBAL DEFAULT 12
__dbcl_db_key_range_ret@@DB4_6
145: 00092770 242 FUNC GLOBAL DEFAULT 12 __mutex_alloc_pp@@DB4_6
146: 000d9500 267 FUNC GLOBAL DEFAULT 12 __env_set_data_dir@@DB4_6

LI Daobing (李道兵)

unread,
Dec 11, 2008, 5:09:08 AM12/11/08
to std...@googlegroups.com, Yingfeng Zhang
2008/12/11 shiwei xu <xushi...@gmail.com>:

> 我明白了。
> 不过这样让我觉得 so 的使用挺"恐怖"。因为它的symbol是全局的。
> 也就是说,我在so中定义任意一个函数名/全局变量名,都得考虑是否和其他so重名了。
我刚才查了一下 ld 的帮助, 有两个选项是用于解决这个问题的

-Bsymbolic
When creating a shared library, bind references to global
symbols to the definition within the shared library, if any.
Normally, it is possible for a program linked against a shared library
to override the definition within the shared library. This option is
only meaningful on ELF platforms which support shared libraries.

-Bsymbolic-functions
When creating a shared library, bind references to global
function symbols to the definition within the shared library, if any.
This option is only meaningful on ELF platforms which support shared
libraries.

Reply all
Reply to author
Forward
0 new messages