私のプロジェクトでは、単純なイベント システムに Loki::Functor を使用しています。イベントには、いくつかのパラメーターを受け取るハンドラー関数があります。この場合は と呼びPrintEventString
ます。キューに入れるには、イベント ハンドラーに同じプロトタイプ (私の場合はvoid func(void)
. したがってCreateEvent
、ハンドラーを受け取り、そこからファンクターを作成し、パラメーターをバインドして、void f (void)
プロトタイプを作成します。functor を呼び出す前にデータ ソースを破棄するまで (2 番目の例、一時的に作成された文字列)、すべてがうまくいきます (ローカル変数に格納された文字列を使用する最初の例)。コードは次のとおりです。
#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;
}
これはコンパイル、実行されますが、2 番目のテストは機能せず、valgrind は一連のエラーをスローします。
==30296== Memcheck、メモリエラー検出器 ==30296== Copyright (C) 2002-2010、および Julian Seward らによる GNU GPL です。 ==30296== Valgrind-3.6.1 と LibVEX を使用。著作権情報については -h で再実行してください ==30296== コマンド: ./main ==30296== テスト: ハローワールド ==30296== サイズ 4 の無効な読み取り ==30296== at 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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f2640 は、解放されたサイズ 24 のブロック内の 8 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/lib/libc-2.14.so 内) ==30296== ==30296== サイズ 4 の無効な読み取り ==30296== at 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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f263c は、解放されたサイズ 24 のブロック内の 4 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/lib/libc-2.14.so 内) ==30296== ==30296== サイズ 4 の無効な読み取り ==30296== at 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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f2638 は、解放されたサイズ 24 のブロック内の 0 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/lib/libc-2.14.so 内) ==30296== ==30296== サイズ 4 の無効な読み取り ==30296== at 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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f2638 は、解放されたサイズ 24 のブロック内の 0 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f264e は、解放されたサイズ 24 のブロック内の 22 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/lib/libc-2.14.so 内) ==30296== ==30296== サイズ 4 の無効な読み取り ==30296== at 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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f2648 は、解放されたサイズ 24 のブロック内の 16 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/lib/libc-2.14.so 内) ==30296== ==30296== サイズ 4 の無効な読み取り ==30296== at 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== by 0x8048E7A: メイン (main.cpp:26) ==30296== アドレス 0x42f2638 は、解放されたサイズ 24 のブロック内の 0 バイトです ==30296== at 0x4026B2C: operator delete(void*) (/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: (メインの下) (/lib/libc-2.14.so 内)
ファンクタが渡されたオブジェクトへの参照のみを取得すると思われます。オブジェクトは(一時的に作成されたものとして)破棄され、問題が発生します。しかし、ここで何が間違っているのでしょうか? 環境を破壊できるように、バインディングは環境の一部を保存するために使用されると思いました (Andrei が彼の本で説明しているように)。