我在我的項目中使用Loki :: Functor進行簡單的事件系統。該事件的處理函數需要一些參數。在這種情況下,它被稱爲PrintEventString
。爲了將它放入隊列中,事件處理程序必須具有相同的原型 - 在我的例子中,void func(void)
。因此CreateEvent
需要處理程序,從它創建函子並綁定參數,從而產生void f (void)
原型。一切都很順利(第一個例子是存儲在本地變量中的字符串),直到我在調用函數之前銷燬數據源(第二個示例,臨時創建的字符串)。下面是代碼:Loki函子 - 內存問題
#include <climits>
#include <string>
#include <iostream>
#include "Loki/Functor.h"
void PrintEventString(std::string str)
{
std::cout << "Test: " << str << std::endl;
}
Loki::Functor<void> CreateEvent (std::string str)
{
Loki::Functor<void, TYPELIST_1(std::string)> handler(PrintEventString);
Loki::Functor<void> event (Loki::BindFirst(handler, str));
return event;
}
int main (void)
{
std::string hello("hello");
Loki::Functor<void> eventTestLocal(CreateEvent(hello));
eventTestLocal();
Loki::Functor<void> eventTestTemp(CreateEvent("Hello world"));
eventTestTemp();
return 0;
}
這將編譯,執行,但第二次測試簡化版,工作和Valgrind的拋出一堆錯誤:
==30296== Memcheck, a memory error detector ==30296== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==30296== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info ==30296== Command: ./main ==30296== Test: Hello world ==30296== Invalid read of size 4 ==30296== at 0x40EB655: std::basic_string, std::allocator >::basic_string(std::string const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f2640 is 8 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so) ==30296== ==30296== Invalid read of size 4 ==30296== at 0x40EAD96: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f263c is 4 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so) ==30296== ==30296== Invalid read of size 4 ==30296== at 0x40EADA5: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f2638 is 0 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so) ==30296== ==30296== Invalid read of size 4 ==30296== at 0x40EADB3: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f2638 is 0 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so) ==30296== ==30296== Invalid read of size 1 ==30296== at 0x40294BA: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40EADF7: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x40EB68F: std::basic_string, std::allocator >::basic_string(std::string const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f264e is 22 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so) ==30296== ==30296== Invalid read of size 4 ==30296== at 0x40294E8: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40EADF7: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x40EB68F: std::basic_string, std::allocator >::basic_string(std::string const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f2648 is 16 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so) ==30296== ==30296== Invalid read of size 4 ==30296== at 0x40EADF8: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x40EB68F: std::basic_string, std::allocator >::basic_string(std::string const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x8049C4F: Loki::Functor, Loki::SingleThreaded>::operator()(std::string&) (Functor.h:779) ==30296== by 0x8049B59: Loki::BinderFirst, Loki::SingleThreaded> >::operator()() (Functor.h:908) ==30296== by 0x80492D6: Loki::Functor::operator()() (Functor.h:776) ==30296== by 0x8048E7A: main (main.cpp:26) ==30296== Address 0x42f2638 is 0 bytes inside a block of size 24 free'd ==30296== at 0x4026B2C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==30296== by 0x40E9C7A: std::string::_Rep::_M_destroy(std::allocator const&) (in /usr/lib/libstdc++.so.6.0.16) ==30296== by 0x41A0232: (below main) (in /lib/libc-2.14.so)
我懷疑仿函數僅取一個參考傳遞的對象,然後被銷燬(如臨時創建)並且問題開始。但是我在這裏做錯了什麼?我認爲綁定是用來存儲部分環境的(正如Andrei在他的書中所描述的那樣),這樣環境就可以被破壞。
您能否在Loki的版本上添加更多信息以及如何編譯源代碼?它不在這裏編譯,因爲我的Loki版本使用'LOKI_TYPELIST_1'而不是'TYPELIST_1'。 – evnu
@evnu:我有本書提供的鏈接的正式版本。我能看到的唯一版本是最後的庫更新:2001年6月20日 –
項目網站http://loki-lib.sourceforge.net/在http://sourceforge.net/projects/loki-lib/files下列出了更多版本/ Loki/ – evnu