14

I've got this loop here for a game bot which requires a __try __except to prevent insta-crashing when the code is injected. However, I'm getting the error: Cannot use __try in functions that require object unwinding fix.

I've looked through all function calls inside of this function, and not a single one of them contain a nested __try __except and I'm also building with /EHs.

Here's my code;

void bot::logic::loop()
{
    while (true)
    {
        __try
        {
            if (bot::logic::should_close())
                exit(33062);

            om::refresh_minions();

            if (local_player::is_threatened())
                local_player::handle_threat();

            if (local_player::is_in_turret())
            {
                utils::move_to_suitable_pos();
                std::this_thread::sleep_for(12s);
            }

            object* localplayer = obj_local_player;
            bot::logic::calculate_buys(localplayer->current_gold);

            obj_manager* manager = (obj_manager*)(m_base + o_obj_manager);
            for (int32_t i = 0; i < manager->highest_index; i++)
            {
                object* this_object = manager->ptrs[i];

                if (this_object)
                {      
                    if (is_minion(this_object) == 3073)
                        if (local_player::object_is_enemy(this_object))
                            if (utils::is_object_mid(this_object))
                                if (is_alive(this_object) == TRUE)
                                    utils::Log("all passed");

                    if (local_player::object_is_enemy(this_object) && utils::is_object_mid(this_object) && is_alive(this_object) == TRUE && is_minion(this_object) == 3073)
                    {
                        object* enemy_minion = this_object;

                        for (int i = 0; i < game::minion_maxed_index; i++)
                        {
                            bot::logic::moving_to_cs_loop(om_ally_minions[i].minion_object, enemy_minion);
                            bot::logic::csing_loop();
                        }
                    }
                }
            }
            std::this_thread::sleep_for(100ms);
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {};
    }
}

Can anyone tell me which objects 'require unwinding' and how I can prevent this error?

EDIT: I've found the error occurs within the code;

if (is_minion(this_object) == 3073)
    if (local_player::object_is_enemy(this_object))
        if (utils::is_object_mid(this_object))
            if (is_alive(this_object) == TRUE)
                utils::Log("all passed");
hellow
  • 12,430
  • 7
  • 56
  • 79
siroot
  • 193
  • 1
  • 2
  • 9
  • Related with a broken link: https://stackoverflow.com/questions/24748384/very-simple-code-and-getting-error-c2712-could-not-understand-why#24748437 – kabanus Aug 06 '18 at 06:13
  • 3
    Note that `__try` and `__except` are not standard C++. This is Microsoft stuff. For portability, use `try` and `catch`. – Pete Becker Aug 06 '18 at 11:49

3 Answers3

10

Anyway I would suggest you move the code within __try/__except to an own function then call it, that way the stack unwinding occurs in the other function.

e.g.

void loop()
{
  __try  { loopimpl(); }
  __except(EXCEPTION_EXECUTE_HANDLER) {};
}

void loopimpl()
{
  while (true) { ... }
}
AndersK
  • 35,813
  • 6
  • 60
  • 86
5

Move __try/__except upper in call hierarchy

void test() {
    myClass m;
    __try
    {
        m.run();
    }
    __except (GenerateDump(GetExceptionInformation())){}
}
int main()
{
    test();
}

Result: Error C2712 Cannot use __try in functions that require object unwinding ...

But:

void test() {
    myClass m;  
    m.run();
}
int main()
{
    __try
    {
        test();
    }
    __except (GenerateDump(GetExceptionInformation())) {}
}

Result: OK

Piotr Sydow
  • 71
  • 1
  • 2
2

I've workarounded that by a labda function beginning from the C++11. Works specifically in the msvc (2015, 2017, ...). The /EH* command line option must be used.

std::vector<...> a;

[&]() {
  __try {
    a.resize(...);
    ...
    [&]() {
      std::vector<...> b;
    }();
  }
  __finally {
    ... 
  }
}();

Or more universal variant, for example, in the main:

int main()
{
    std::vector<...> a;
    return [&]() -> int { __try {
        return [&]() -> int {
            std::vector<...> b;
            return 0;
        }();
    }
    __finally {
        // close all handles here...
    }
    return 0;
    }();
}

Some disadvantage of this is that you still can not return c++ objects and must assign them through all labda functions to the most outer scope out of the __try scope.

std::string foo()
{
    std::string ret;

    [&]() { __try {
        [&]() {
            // return std::string{"123"}; // error C2712: Cannot use __try in functions that require object unwinding
            ret = std::string{"123"};
        }();
    }
    __finally {
        // close all handles here...
    }
    }();

    return ret;
}

https://godbolt.org/z/Kxxqrc1hh

If you want to enable the __try/__except/__finally under GCC, then can look at something like that: http://www.programmingunlimited.net/siteexec/content.cgi?page=libseh

Andry
  • 2,273
  • 29
  • 28