Я использую 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, 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)
Я подозреваю, что функтор берет только ссылку на переданный объект, который затем уничтожается (как временно созданный) и начинаются проблемы. Но что я здесь делаю не так? Я предположил, что привязка должна использоваться для хранения части окружения (как Андрей описывает в своей книге), чтобы окружение могло быть уничтожено.