我在我的项目中使用 Loki::Functor 来构建一个简单的事件系统。该事件的处理函数采用一些参数。在这种情况下,它被称为PrintEventString
。为了将它放入队列中,事件处理程序必须具有相同的原型——在我的例子中,void func(void)
. 所以CreateEvent
获取处理程序,从中创建函子并绑定参数,从而产生void f (void)
原型。一切正常(第一个示例,字符串存储在局部变量中),直到我在调用仿函数之前销毁数据源(第二个示例,临时创建的字符串)。这是代码:
#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,内存错误检测器 ==30296== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==30296== 使用 Valgrind-3.6.1 和 LibVEX;使用 -h 重新运行以获取版权信息 ==30296== 命令:./main ==30296== 测试:你好世界 ==30296== 大小为 4 的读取无效 ==30296== 在 0x40EB655: std::basic_string, std::allocator >::basic_string(std::string const&) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f2640 在大小为 24 的块中是 8 个字节 ==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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so) ==30296== ==30296== 大小为 4 的读取无效 ==30296== 在 0x40EAD96:std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f263c 在大小为 24 的块内有 4 个字节已释放 ==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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so) ==30296== ==30296== 大小为 4 的读取无效 ==30296== 在 0x40EADA5:std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f2638 是大小为 24 的块内的 0 个字节 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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so) ==30296== ==30296== 大小为 4 的读取无效 ==30296== 在 0x40EADB3: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f2638 是大小为 24 的块内的 0 个字节 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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so) ==30296== ==30296== 大小为 1 的读取无效 ==30296== 在 0x40294BA:memcpy(在 /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so 中) ==30296== by 0x40EADF7: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x40EB68F: std::basic_string, std::allocator >::basic_string(std::string const&) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f264e 在大小为 24 的块内是 22 个字节 ==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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so) ==30296== ==30296== 大小为 4 的读取无效 ==30296== 在 0x40294E8:memcpy(在 /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so 中) ==30296== by 0x40EADF7: std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x40EB68F: std::basic_string, std::allocator >::basic_string(std::string const&) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f2648 在大小为 24 的块内是 16 个字节 ==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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so) ==30296== ==30296== 大小为 4 的读取无效 ==30296== 在 0x40EADF8:std::string::_Rep::_M_clone(std::allocator const&, unsigned int) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x40EB68F: std::basic_string, std::allocator >::basic_string(std::string const&) (在 /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== 由 0x8048E7A: 主 (main.cpp:26) ==30296== 地址 0x42f2638 是大小为 24 的块内的 0 个字节 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&) (在 /usr/lib/libstdc++.so.6.0.16 中) ==30296== by 0x41A0232: (低于 main) (in /lib/libc-2.14.so)
我怀疑函子只引用传递的对象,然后将其销毁(作为临时创建的)并且问题开始了。但是我在这里做错了什么?我认为绑定将用于存储环境的一部分(正如安德烈在他的书中所描述的那样),以便可以破坏环境。