2017-09-26 1 views
0

이상한 일이 일어나고 있습니다. 콜백 함수를 바인딩하고 있는데 (코드의 다른 부분에서 여러 번 했음), 어떤 이유로 이번에는 소멸자가 호출되고 콜백 함수가 세그 폴트가됩니다.std :: bind는 소멸자에 세분화 오류를 발생시킵니다.

다음은 모든 불필요한 물건 내 코드는

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 오류 GUILogicComponent.cpp

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); 
}; 

을 제거

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) 

여기 여기 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; 

어떤 도움이 크게 감사 것을하고 무엇을 내 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)); 
} 

에 Mousecode 정의의 d ... 고마워요! immediatly이 줄 끝에서 파괴

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

:

+1

'bind'는 C++ 11에 추가되었을 때 대체로 쓸모가 없었습니다; 나는 여기서 람다 (lambda)로 더 명확하게 할 수없는 것을 볼 수 없다. 그렇게하는 것을 고려하십시오. 마술이 적고, 사본이 무엇인지, 참조가 무엇인지에 대해 더욱 분명합니다. – Yakk

+0

'this' 앞에 별표가없는'std :: bind (& GUILogicComponent :: clicked, this, ...)'를 시도하십시오. 나는 당신이'GUILogicComponent'의 복사본을 만들고 그것을'bind'에 넘겨 준다고 생각합니다. –

+0

감사합니다. @IgorTandetnik –

답변

1

는 현재 *this를 통과하는 임시 복사본을 만들 수 있습니다.

다른 복사/이동 생성자 및 연산자가 표시되지 않으며 사용자가 코딩하지 않은 것 같습니다. What is The Rule of Three?
같은 포인터를 두 번 삭제합니다.

구성 요소가 소유권을 갖고있는 것으로 보이므로 std:::unique_ptr을 사용해야합니다.

+0

와우, 나는 믿을 수 없을 정도로 어리 석다! 고맙습니다. 나는 이것을 * 참조하지 않기 위해 * 삭제했습니다. 참고 사항 : 내 엔티티에 shared_ptr을 사용하는 것을 고려해야합니까? 엔티티에는 소유권이 있지만 개별 구성 요소가 서로에 대해 알아야 할 경우가 있습니다. 내가 해왔 던 방식은 포인터를 엔티티에 전달하여 소멸자에서 삭제하지만 참조를 다른 구성 요소에 전달하는 것입니다. –

+0

@ ThorCorreia 구성 요소가 해당 소유권을 공유하는 경우 그렇습니다. 대신 shared_ptr을 사용하십시오. –

관련 문제