【发布时间】:2016-04-11 05:20:41
【问题描述】:
这个问题与我一年前问的previous question 有关。 我正在使用很久以前用 C 语言编写的 WordNet 3.0(我认为大约是 1996 年)。
为了尽量远离内存管理,我询问如何将 std::shared_ptr 包裹在 WordNet 使用的旧 struct Synset 周围。
reference table 显示 WordNet-3.0 功能,检查the actual header 显示SynsetPtr,
traceptrs_ds 和 findtheinfo_ds 返回的函数是指向 ss 或 Synset 的指针。
在我的previous question 中我选择移除指针,
然后将其包裹在 shared_ptr 周围,如下所示:
std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
(findtheinfo_ds(searchstr, pos, ptr_type, sense_num),
free_syns);
std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
(traceptrs_ds(synptr, ptr_type, pos, depth),
free_synset);
我有两个循环,一个通过nextss 迭代senses,另一个通过调用traceptrs_ds 遍历树列表。
这是两个循环(过于简单):
std::shared_ptr<Synset> synsets;
synsets = std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
(findtheinfo_ds(const_cast<char*>(key.c_str()), lexical, HYPERPTR, ALLSENSES),free_syns);
if (synsets)
{
std::shared_ptr<Synset> sense_ptr = synsets;
while(sense_ptr)
{
graph g = graph();
iterate(sense_ptr, nullptr, g, 0, lexical);
sense_ptr = std::shared_ptr<std::remove_pointer<SynsetPtr>::type>(sense_ptr->nextss);
}
}
iterate(
std::shared_ptr<Synset> ptr,
std::shared_ptr<layer> last,
graph & rhs,
int i,
int lexical
)
{
while (ptr)
{
i++;
ptr = std::shared_ptr<std::remove_pointer<SynsetPtr>::type>
(traceptrs_ds(ptr.get(), HYPERPTR, lexical, 1), free_synset);
}
}
据我了解(请随时纠正我)许多std::shared_ptr 都围绕着相同的记忆,
当调用它们的析构函数时,它们会尝试释放相同的内存。
如何防止这种情况发生?
我知道findtheinfo_ds 返回一个链接列表,并且每次调用traceptrs_ds 似乎都会迭代该列表。
我认为最好的方法是只包装一个std::shared_ptr,它将调用Synset 析构函数free_synset,而不是多次这样做。
我怎样才能阻止这种情况发生?
假设没有解决方案可以防止这种情况发生,
映射到同一个区域的众多std::shared_ptr 的析构函数如何只释放一次?
我想这是一种糟糕/丑陋的方式,但它可能更容易?
valgrind 输出:
==3066== Invalid read of size 8
==3066== at 0x52C3B4C: free_synset (in /usr/lib/libwordnet-3.0.so)
==3066== by 0x4E6E2D9: std::_Sp_counted_deleter<ss*, void (*)(ss*), std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:463)
==3066== by 0x403C5F: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:149)
==3066== by 0x403AD8: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:666)
==3066== by 0x4E61DB7: std::__shared_ptr<ss, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:914)
==3066== by 0x4E61DD1: std::shared_ptr<ss>::~shared_ptr() (shared_ptr.h:93)
==3066== by 0x4E6161A: smnet::hyper_handler::operator()(std::string, int) (hyper_handler.cpp:22)
==3066== by 0x4036D6: main (hypernym.cpp:16)
==3066== Address 0x10 is not stack'd, malloc'd or (recently) free'd
==3066== Process terminating with default action of signal 11 (SIGSEGV)
==3066== Access not within mapped region at address 0x10
==3066== at 0x52C3B4C: free_synset (in /usr/lib/libwordnet-3.0.so)
==3066== by 0x4E6E2D9: std::_Sp_counted_deleter<ss*, void (*)(ss*), std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:463)
==3066== by 0x403C5F: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:149)
==3066== by 0x403AD8: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:666)
==3066== by 0x4E61DB7: std::__shared_ptr<ss, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:914)
==3066== by 0x4E61DD1: std::shared_ptr<ss>::~shared_ptr() (shared_ptr.h:93)
==3066== by 0x4E6161A: smnet::hyper_handler::operator()(std::string, int) (hyper_handler.cpp:22)
==3066== by 0x4036D6: main (hypernym.cpp:16)
==3066== LEAK SUMMARY:
==3066== definitely lost: 0 bytes in 0 blocks
==3066== indirectly lost: 0 bytes in 0 blocks
==3066== possibly lost: 251 bytes in 8 blocks
==3066== still reachable: 19,964 bytes in 90 blocks
==3066== suppressed: 0 bytes in 0 blocks
==3066== Reachable blocks (those to which a pointer was found) are not shown.
==3066== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==3066==
==3066== For counts of detected and suppressed errors, rerun with: -v
==3066== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
fish: “valgrind --leak-check=full ./hy…” terminated by signal SIGSEGV (Address boundary error)
【问题讨论】:
标签: c++ pointers c++11 shared-ptr wordnet