I use Loki::Functor in my project for a simple event system. The event has its handler function taking some parameters. In this case, it is called PrintEventString. In order to put it in the queue, the event handlers must have same prototypes - in my case, void func(void). So CreateEvent takes the handler, creates functor from it and binds the parameter, resulting in void f (void) prototype. Everything goes fine (first example with string stored in local variable), until I destroy the data source before calling functor (second example, string created temporarily). Here is the code:
#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;
}
This compiles, executes, but the second test does't work and valgrind throws a bunch of errors:
==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)
I suspect the functor to take only a reference to passed object, which is then destroyed (as temporarily created) and the problems begin. But what am I doing wrong here? I supposed the binding is to be used for storing part of the environment (as Andrei describes in his book), so that the environment can be destroyed.
LOKI_TYPELIST_1instead ofTYPELIST_1. - evnu