2017-09-26 59 views
0

因此發生了一些奇怪的事情。我綁定了一個回調函數(我在代碼的其他部分已經做了好幾次),但由於某種原因,這次它導致析構函數被調用,並且在它上面存在段錯誤...std :: bind在析構函數上導致了分段錯誤

這裏是我與所有多餘的東西代碼剝離

GUILogicComponent.h

class GUILogicComponent : public LogicComponent { 
private: 
    std::function<void()> callback; 
    EventListenerComponent* eventListener; 
    SpriteComponent& sprite; 
public: 
    GUILogicComponent(EventListenerComponent* el, SpriteComponent& s, std::function<void()> cb); 
    ~GUILogicComponent(); 
    void clicked(int x, int y); 
}; 

GUILogicComponent.cpp

GUILogicComponent::GUILogicComponent(EventListenerComponent* el, SpriteComponent& s, std::function<void()> cb) : eventListener(el), sprite(s), callback(cb) { 
    eventListener->addMouseFunction(std::bind(&GUILogicComponent::clicked, *this, std::placeholders::_1, std::placeholders::_2), SDL_BUTTON_LEFT); 
    // TODO: Binding causes seg fault 
} 

GUILogicComponent::~GUILogicComponent() { 
    delete eventListener; 
} 

void GUILogicComponent::clicked(int x, int y) { 
    if (sprite.pointInSprite(x, y)) 
     callback(); 
} 

的GDB錯誤

Thread 3 received signal SIGSEGV, Segmentation fault. 
0x0000000100004e73 in Thor_Lucas_Development::GUILogicComponent::~GUILogicComponent (
    this=<error reading variable: Cannot access memory at address 0x7fff5f3ffff8>) 
    at Components/GUILogicComponent.cpp:11 
11 GUILogicComponent::~GUILogicComponent() { 

不知道發生了什麼事。奇怪的是,刪除其他構造函數參數(刪除精靈和回調,並註釋掉所有相關的代碼),而不是我的這個錯誤。

Thread 3 received signal SIGSEGV, Segmentation fault. 
0x00000001000027b8 in std::__1::__tree<std::__1::__value_type<Thor_Lucas_Development::Mousecode, std::__1::function<void (int, int)> >, std::__1::__map_value_compare<Thor_Lucas_Development::Mousecode, std::__1::__value_type<Thor_Lucas_Development::Mousecode, std::__1::function<void (int, int)> >, std::__1::less<Thor_Lucas_Development::Mousecode>, true>, std::__1::allocator<std::__1::__value_type<Thor_Lucas_Development::Mousecode, std::__1::function<void (int, int)> > > >::destroy(std::__1::__tree_node<std::__1::__value_type<Thor_Lucas_Development::Mousecode, std::__1::function<void (int, int)> >, void*>*) (this=0x10070c768, __nd=0x1007365d0) 
    at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:1377 
1377  if (__nd != nullptr) 

這裏的Mousecode定義在我Util.h

/** 
* Used to store a mouse state for mapping to functions. 
*/ 
struct Mousecode { 
    Uint8 button; /**< The mouse button pressed (i.e\. SDL_BUTTON_LEFT). */ 
    Uint8 state; /**< The state of the mouse button (i.e\. SDL_RELEASED). */ 
}; 

inline bool const operator==(const Mousecode& l, const Mousecode& r) { 
    return (l.button == r.button) && (l.state == r.state); 
} 

inline bool const operator<(const Mousecode& l, const Mousecode& r) { 
    return (l.button < r.button) || ((l.button == r.button) && (l.state < r.state)); 
} 

這裏是EventListenerComponent做

void EventListenerComponent::addMouseFunction(std::function<void(int, int)> func, Uint8 button, Uint8 state) { 
    Mousecode code = {button, state}; 
    mouseFunctionMap[code] = func; 
} 

而且mouseFunctionMap

std::map<Mousecode, std::function<void(int, int)>> mouseFunctionMap; 

任何幫助將不勝感激d ...謝謝!

+1

當bind被添加到C++ 11時,'bind'大多已經過時;在這裏我什麼都看不到,用拉姆達不能做得更清楚。考慮這樣做;更少的魔力,更明確的是什麼是副本和什麼是參考。 – Yakk

+0

嘗試'std :: bind(&GUILogicComponent :: clicked,this,...)',在'this'之前沒有星號。我懷疑你正在複製'GUILogicComponent'並將其傳遞給'bind'。 –

+0

謝謝! @IgorTandetnik –

回答

1

您正在創建一個臨時副本路過這裏*this

eventListener->addMouseFunction(std::bind(&GUILogicComponent::clicked, *this, std::placeholders::_1, std::placeholders::_2), SDL_BUTTON_LEFT); 

這是該行後立刻銷燬。

您沒有顯示其他複製/移動構造函數和操作符,我懷疑你沒有編碼它們。請參閱What is The Rule of Three?
這會導致相同指針的雙重刪除。

您應該使用std:::unique_ptr,因爲您的組件似乎擁有它的所有權。

+0

哇,我覺得非常愚蠢!謝謝,我只是刪除了*以不解除引用。附註:我應該考慮對我的實體使用shared_ptr嗎?實體擁有所有權,但有時單個組件需要彼此瞭解。我一直在做的方式是將指針*傳遞給要在析構函數中刪除的實體,但將引用傳遞給其他組件。 –

+0

@ThorCorreia如果您的組件共享該所有權,則是,請改用shared_ptr。 –