简体   繁体   中英

Program with bound method is built but fails to launch

Consider following code compiled under C++11 with gcc:

#include <cstdio>
#include <functional>
#include <unordered_map>
using namespace std;
using namespace std::placeholders;

class Box
{
    char* box;

public:
    Box(): box(new char[128]) {}
    ~Box()
    {
        delete[] this->box;
    }
    void example(int a, int b)
    {
        printf("%d %d", a, b);
    }
};

Box box;
unordered_map<char, function<void(int, int)>> methods = {
    {'a', bind(&Box::example, box, _1, 8)}
};

int main()
{
    fputs("Main called.", stdout);
    return 0;
}

The program can be built without errors but an attempt to launch it is ignored or results in failure.

On Windows 10, launching the resulted exe file via command prompt just prints a blank line with no explanation, even though program should output Main called. .

When running this in VS Code's integrated terminal I get somewhat better error message:

The terminal process "C:\WINDOWS\System32\cmd.exe /d /c {path to exe file} failed to launch (exit code: 3221226356).

When I change the Box definition to one that doesn't use a pointer for the box member it works:

class Box
{
    char box[128];

public:
    void example(int a, int b)
    {
        printf("%d %d", a, b);
    }
};

What gives?

This is a combination of several arcane aspects of C++:

unordered_map<char, function<void(int, int)>> methods = {
    {'a', bind(&Box::example, box, _1, 8)}
};

If you change this to:

unordered_map<char, function<void(int, int)>> methods = {
    {'a', bind(&Box::example, &box, _1, 8)}
};

The code should still compile, and it will run without errors. Verified with gcc 10.

Your class Box violates the Rule Of Three . If a Box object gets copy-constructed there will be copies of a single Box object with the same pointer, and when both of them get destroyed, an attempt will be made to delete the same pointer multiple times. Hillarity ensues.

So that's the first factor that raised your issue: your class was not Rule Of 3 compliant.

The second issue is that std::bind is quite versatile and has multiple overloads. The overload you used in your program effectively boils down that (as part of its inner workings) an internal copy of the box object gets made, triggering the Rule Of 3 violation.

But std::bind can also work here using a pointer to the object with the bound method, and this avoids the need to make a copy of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM