Другое С/С++ Вопрос - Ответ

Roger571

Известный
58
31
Пытаюсь разобраться, как работать с boost::regex и в процессе захотелось написать более удобную обертку под свои нужды. Но есть одно но, никак не могу понять почему объект boost::smatch невалидно передается по ссылке.
Вот сам код:
C++:
#include "main.h"

bool easyRegex(std::string sString, boost::regex rRegex, boost::smatch &sResults, int iArg, char *szRegexName)
{
    if (boost::regex_search(sString, sResults, rRegex))
    {
        if (sResults.size() < iArg) 
        {
            printf("Error %s! | Size: %d < %d\n", szRegexName, sResults.size(), iArg);
            return false;
        }

        printf("[easyRegex] Pointer: %p\n", sResults);
        printf("[easyRegex] Size: %d\n", sResults.size());

        for (int i = 1; i < sResults.size(); i++)
            printf("[easyRegex] [%d] %s\n", i, sResults.str(i).c_str());

        return true;
    }
    else
    {
        printf("Error %s! | regex_search\n", szRegexName);
        return false;
    }
}

int main()
{
    std::cout << "Hello!\n";
   
    std::string sTest = "sdf 24 string 3452 43556aad";
    boost::regex regex("\\w+ ([\\d]+) ([\\w]+) ([\\d]+) ([\\d\\w]+)");
    boost::smatch result;
   
    if (easyRegex(sTest, regex, result, 5, "test"))
    {
        printf("[main] Pointer: %p\n", result);
        printf("[main] Size: %d\n", result.size());

        for (int i = 1; i < result.size(); i++)
            printf("[main] [%d] %s\n", i, result.str(i).c_str());
    }

    system("pause");
}
А вот результат его выполнения:
C++:
[easyRegex] Pointer: 03901658
[easyRegex] Size: 5
[easyRegex] [1] 24
[easyRegex] [2] string
[easyRegex] [3] 3452
[easyRegex] [4] 43556aad
[main] Pointer: 03901658
[main] Size: 5

И далее идет краш "Expression: string iterators incompatible".
Хотелось бы разобраться, что же все-таки не так
 

SR_team

like pancake
BH Team
4,720
6,368
Пытаюсь разобраться, как работать с boost::regex и в процессе захотелось написать более удобную обертку под свои нужды. Но есть одно но, никак не могу понять почему объект boost::smatch невалидно передается по ссылке.
Вот сам код:
C++:
#include "main.h"

bool easyRegex(std::string sString, boost::regex rRegex, boost::smatch &sResults, int iArg, char *szRegexName)
{
    if (boost::regex_search(sString, sResults, rRegex))
    {
        if (sResults.size() < iArg)
        {
            printf("Error %s! | Size: %d < %d\n", szRegexName, sResults.size(), iArg);
            return false;
        }

        printf("[easyRegex] Pointer: %p\n", sResults);
        printf("[easyRegex] Size: %d\n", sResults.size());

        for (int i = 1; i < sResults.size(); i++)
            printf("[easyRegex] [%d] %s\n", i, sResults.str(i).c_str());

        return true;
    }
    else
    {
        printf("Error %s! | regex_search\n", szRegexName);
        return false;
    }
}

int main()
{
    std::cout << "Hello!\n";
  
    std::string sTest = "sdf 24 string 3452 43556aad";
    boost::regex regex("\\w+ ([\\d]+) ([\\w]+) ([\\d]+) ([\\d\\w]+)");
    boost::smatch result;
  
    if (easyRegex(sTest, regex, result, 5, "test"))
    {
        printf("[main] Pointer: %p\n", result);
        printf("[main] Size: %d\n", result.size());

        for (int i = 1; i < result.size(); i++)
            printf("[main] [%d] %s\n", i, result.str(i).c_str());
    }

    system("pause");
}
А вот результат его выполнения:
C++:
[easyRegex] Pointer: 03901658
[easyRegex] Size: 5
[easyRegex] [1] 24
[easyRegex] [2] string
[easyRegex] [3] 3452
[easyRegex] [4] 43556aad
[main] Pointer: 03901658
[main] Size: 5

И далее идет краш "Expression: string iterators incompatible".
Хотелось бы разобраться, что же все-таки не так
Блед, хватит страдать - Бери STL. А если хочется "easyRegex", то бери SRStrings или целый Qt.
 

Roger571

Известный
58
31
Блед, хватит страдать - Бери STL. А если хочется "easyRegex", то бери SRStrings или целый Qt.
Да я могу уже взять нормальные решения, но я хочу понять, в чем я конкретно тут проебался.
Просто для себя понять почему вот так случается, что через cout объекты доступны, а любое взаимодействие - краш
 

san0

Известный
Друг
411
267
Просто для себя понять почему вот так случается
Мне кажется, что проблема заключается в том, что std::string sString был инициализирован с помощью конструктора копирования, и его цикл жизни был только в пределеах функции easyRegex().
Операция regex_search была выполнена над строкой, которая, по сути, не имеет ничего общего с sTest (незавимая копия), но к ее элементам все равно хотят достучаться в тот момент, когда их существование явно не гарантировано.
К слову говоря, полученый результат мог бы быть и другим. Точнее, здесь все аналогично тому, как пытаться получить доступ к данным, расположеным в освобожденной памяти - иногда это, возможно, и работает.
В общем, вот этот вектор boostorg/regex(https://github.com/boostorg/regex/blob/5d990fd751a8c149dd47fbaf24eaaffd1bde3bd5/include/boost/regex/v4/match_results.hpp#L577) в результате и ломается
Подводя итоги, следует передать строку тоже по ссылке bool easyRegex(std::string& sString, ... etc ...
Так в STL часто переносят то, что хорошо показало себя в boost (конечно с фиксами всякими (напр. filesystem)).
 
Последнее редактирование:
  • Нравится
Реакции: Roger571

-raymond-

Известный
110
9
крашится игра когда ввожу /skladoff
C++:
bool sliv;
int etap;

void call_main_func()
{
    while (sliv == true)
    {
        stLocalPlayer *player = SF->getSAMP()->getPlayers()->pLocalPlayer;
        int PlayerID;
        PlayerID = SF->getSAMP()->getPlayers()->sLocalPlayerID;
        if (etap == 0)
        {
            player->Say("/getgun 300");
            etap = 1;
            Sleep(1000);
        }
        else if (etap == 1)
        {
            char txtfmt[20];
            sprintf(txtfmt, "/sellgun m4 100 4 %d", PlayerID);
            player->Say(txtfmt);
            etap = 0;
            Sleep(1000);
        }
    }
}

bool CALLBACK inRPC(stRakNetHookParams *params)
{
    if (params->packetId == ScriptRPCEnumeration::RPC_ScrClientMessage)
    {
        uint32_t    len, color;
        char        msg[144];

        params->bitStream->ResetReadPointer();
        params->bitStream->Read(color);
        params->bitStream->Read(len);
        params->bitStream->Read(msg, len);
        msg[len] = '\0';

        if (strstr(msg, "Не флуди"))
            return false;
    }
    return true;
}

void CALLBACK sliv_activate(std::string param)
{
    if (sliv == true) sliv = false;
    else
    {
        call_main_func();
    }
}

void CALLBACK mainloop()
{
    static bool init = false;
    if (!init)
    {
        if (GAME == nullptr || GAME->GetSystemState() != eSystemState::GS_PLAYING_GAME || !SF->getSAMP()->IsInitialized())
            return;
        SF->getRakNet()->registerRakNetCallback(RakNetScriptHookType::RAKHOOK_TYPE_INCOMING_RPC, inRPC);
        SF->getSAMP()->registerChatCommand("skladoff", sliv_activate);
        init = true;
    }

}
 

Roger571

Известный
58
31
Мне кажется, что проблема заключается в том, что std::string sString был инициализирован с помощью конструктора копирования, и его цикл жизни был только в пределеах функции easyRegex()....

Благодарю за пояснение, полезно смотреть исходники буста. Правильно ли понимаю, что результаты в smatch являются указателем на объект в котором осуществляется поиск?
 

Dark_Knight

Me, me and me.
Друг
4,062
2,077
крашится игра когда ввожу /skladoff
Слипы нельзя юзать в командах и коллбеках.
Хотелось бы разобраться, что же все-таки не так
Код:
sResults.str(i).c_str() замени на sResults[i].str().c_str()
upload_2018-7-17_9-44-43.png
 
  • Нравится
Реакции: Roger571

SR_team

like pancake
BH Team
4,720
6,368
я хочу понять, в чем я конкретно тут проебался.
в выборе boost.
Так в STL часто переносят то, что хорошо показало себя в boost
Вот именно. На кой черт тащить буст, который только замедлит компиляцию и увеличит размер бинаря?
 
  • Нравится
Реакции: Roger571

Roger571

Известный
58
31
в выборе boost.

Вот именно. На кой черт тащить буст, который только замедлит компиляцию и увеличит размер бинаря?

Дело в том, что я компилю VS2008 и в STL еще не ввели regex.
Дадада, но на это есть определенные причины

Слипы нельзя юзать в командах и коллбеках.

Код:
sResults.str(i).c_str() замени на sResults[i].str().c_str()
К слову, вчера ночью пробовал и результат не изменился, но проблема и мой вопрос исчерпан благодаря san0
 

Some_Clever_Name

Новичок
13
0
Можно ли сделать коллизию машины без SF? К примеру, по какому-нибудь адресу.

Слышал, что есть оффсет "танк мод" - можно ли его юзать?