c++ - std::bind 导致析构函数出现段错误

标签 c++ c++11 segmentation-fault

所以奇怪的事情发生了。我正在绑定(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() {

不确定发生了什么。奇怪的是,删除其他构造函数参数(删除 sprite 和回调并注释掉所有相关代码)反而给我留下了这个错误。

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)

这是我的 Util.h 中的 Mousecode 定义

/**
 * 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;

任何帮助将不胜感激……谢谢!

最佳答案

您正在创建一个临时拷贝并在此处传递 *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因为您的组件似乎拥有它的所有权。

关于c++ - std::bind 导致析构函数出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46416547/

相关文章:

c++ - 除了直接访问之外,还有其他方法可以更改内存中的值吗?

c++ - 使用 C++ 程序删除 unix 共享内存段

c++ - constexpr 适用于 Ubuntu,但不适用于 MacOS

c++ - 访问模板内部 typedef

c - printf %s 段错误 - 为什么?

c - 在 sprintf 中使用节点元素

c++ - 使用通用函数调用打印结构的所有嵌套成员变量

c++ - 将 std::queue 与 shared_ptr 一起使用?

c++ - 带有 std::make_unique 的 push_back 或 emplace_back

C++拆分输入问题