2016-05-11 99 views
2

我有一個根據傳入的值調用函數的類。函數是void,沒有參數,並存儲在映射中(以及其他一些信息)。調用綁定成員函數時出現分段錯誤

程序編譯和預期,但是當labrador稱爲程序SIGSEVs在GDB以下信息golden_retriever工作的功能(超出#5是出於測試類,並進入實際的代碼):

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000000000 in ??() 
(gdb) where 
#0 0x0000000000000000 in ??() 
#1 0x000000000040dc71 in std::_Mem_fn<void (TestHandlerTwo::*)()>::operator()<, void>(TestHandlerTwo*) const (this=0x6416c0, __object=0x641400) 
    at /usr/include/c++/4.8/functional:601 
#2 0x000000000040d600 in std::_Bind<std::_Mem_fn<void (TestHandlerTwo::*)()> (TestHandlerTwo*)>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>) (this=0x6416c0, 
    __args=<unknown type in /home/master/splint/SplintApp/test, CU 0x1eee, DIE 0x140c8>) 
    at /usr/include/c++/4.8/functional:1296 
#3 0x000000000040c90c in std::_Bind<std::_Mem_fn<void (TestHandlerTwo::*)()> (TestHandlerTwo*)>::operator()<, void>() (this=0x6416c0) at /usr/include/c++/4.8/functional:1355 
#4 0x000000000040bcf3 in std::_Function_handler<void(), std::_Bind<std::_Mem_fn<void (TestHandlerTwo::*)()> (TestHandlerTwo*)> >::_M_invoke(std::_Any_data const&) (
    __functor=...) at /usr/include/c++/4.8/functional:2071 
#5 0x000000000040ab5c in std::function<void()>::operator()() const (this=0x641690) 
    at /usr/include/c++/4.8/functional:2471 

的代碼:

#include <iostream> 
#include <map> 
#include <memory> 

struct command 
{ 
    std::string cmdname;   // console friendly name 
    std::function<void()> execute; // function to call 
}; 

class IHandler 
{ 
public: 
    virtual void parse(int value) = 0; 
}; 

class BaseHandler : public IHandler 
{ 
public: 
    virtual auto getCommandMap() -> std::map<int, command> const = 0; 

    void parse(int value) override 
    { 
     // this normally takes a stream of bytes and parses it but for this example we hardcode it. 
     auto search = getCommandMap().find(value); 
     if (search == getCommandMap().end()) 
     { 
      return; 
     } 
     std::cout << "Function is " << (search->second.execute ? "callable" : "not callable") << std::endl; 
     if (search->second.execute) 
     { 
      search->second.execute(); 
     } 
     return; 
    } 
}; 

void golden_retriever() 
{ 
    std::cout << "Chases cat" << std::endl; 
} 
class TestHandlerTwo : public BaseHandler 
{ 
    std::map<int, command> commandMap = 
    { 
     { 0x02, { "Handled", golden_retriever } }, 
     { 0x03, { "Test", std::bind(&TestHandlerTwo::labrador, this) } } 
    }; 
public: 
    void labrador() 
    { 
     std::cout << "Chases birds" << std::endl; 
    } 
    virtual auto getCommandMap() -> std::map<int, command> const override 
    { 
     return commandMap; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    auto testHandler = std::shared_ptr<IHandler>(new TestHandlerTwo()); 
    testHandler->parse(0x02); 
    testHandler->parse(0x03); 
    return 0; 
} 

的輸出是:

(gdb) run 
Starting program: /home/master/test/main 
Function is callable 
Chases cat 
Function is callable 

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000000000 in ??() 

根據這article和問題已經問StackOverflow,我的bind的用法似乎是正確的,那麼我的代碼有什麼問題?

+1

你怎麼那麼使用的CommandMap?我運行了一個非常簡單的測試,你的代碼工作。 –

+0

給我們一個完整的程序,我們可以編譯和運行。 –

+0

@JohnZwinck完成。 –

回答

1

您正在訪問容器(地圖)已銷燬後的迭代器。

在BaseHandler ::解析

void parse(int value) override 
{ 
    // !!here, you constructs a map, and destruct it immediately 
    // which invalidates the iterator 
    // auto search = getCommandMap().find(value); 
    // if (search == getCommandMap().end()) 
    // { 
    //  return; 
    // } 
    // change to these three lines 
    auto&& commandMap = getCommandMap(); 
    auto&& search = commandMap.find(value); 
    if (search == commandMap.end()) return; 

    std::cout << "Function is " << (search->second.execute ? "callable" : "not callable") << std::endl; 
    if (search->second.execute) 
    { 
     search->second.execute(); 
    } 
    return; 
} 

見BaseHandler :: getCommandMap

// this always create a copy of original map, which considered 
// temporary, destroys after execution of the statement if not 
// being explicitly held. 
virtual auto getCommandMap() -> std::map<int, command> const = 0; 
+0

那麼爲什麼它可以與非成員函數一起工作,但是失敗的成員函數呢?並在Clang/OSX上工作?便飯? –

+0

它出現在最後我只需要'auto commandMap = getCommandMap();' –