почему крашит при отправлении в чат

qrlk

Известный
Автор темы
Друг
411
926
всем привет

предпринимая очередную попытку пофиксить краши https://www.blast.hk/threads/56447/, наткнулся на проблемную часть: отправку результата распознавания в чат без использования сторонних api

я выделил этот момент в отдельный файл, собственно мой вопрос: что я делаю не так и как заставить SendChat() работать так же стабильно, как и AddMessage()

C++:
#include <Windows.h>
#include <vector>
#include <iostream>
#include <string>
#include <cstring>

class sampSendChat {
private:
    HANDLE hThread = NULL;

public:
    sampSendChat() {
        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sampSendChat::init, (LPVOID)this, 0, (LPDWORD)NULL);
    }

    ~sampSendChat() {
        TerminateThread(hThread, 0);
    }

    static LPVOID WINAPI init(LPVOID* lpParam) {
        sampSendChat* sender = (sampSendChat*)lpParam;
        sender->run();

        sender->hThread = NULL;

        return NULL;
    }

    void AddMessage(const std::string& string, int color)
    {
        typedef int(__thiscall* AddMessage)(DWORD, int, const char*, int, int, int);
        static AddMessage addMessage = (AddMessage)((DWORD)GetModuleHandle("samp.dll") + 0x64010);
        static DWORD chatPointer = (DWORD)GetModuleHandle("samp.dll") + 0x21A0E4;

        addMessage(*(DWORD*)chatPointer, 4, string.c_str(), 0, color, 0);
    }



    void SendChat(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        /*
        какой-нибудь способ конвертировать std::string -> const char*, чтобы оно не крашило через n повторений
        */

        if (text[0] == '/')
            sendCommand(cstr);
        else
            sendText(cstr);
    }


    /*крашит через 189 раз*/
    void SendChat1(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        if (text[0] == '/')
            sendCommand(text.c_str());
        else
            sendText(text.c_str());
    }

    /*крашит через 758 раз*/
    void SendChat2(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        char* cstr = new char[text.length() + 1];
        std::strcpy(cstr, text.c_str());

        if (text[0] == '/')
            sendCommand(cstr);
        else
            sendText(cstr);
        delete[] cstr;
    }

    std::vector<char> toVector(const std::string& s) {
        std::vector<char> v(s.size() + 1);
        memcpy(&v.front(), s.c_str(), s.size() + 1);
        return v;
    }

    /*крашит через 215 раз*/
    void SendChat3(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        std::vector<char> v = toVector(text);

        if (text[0] == '/')
            sendCommand(v.data());
        else
            sendText(v.data());

        v.clear();
    }


    void run() {
        Sleep(15000);

        while (true)
        {
            Sleep(100);

            SendChat("test");

            static int counter = 0;
            counter++;

            AddMessage("message sent. Times: " + std::to_string(counter), -1);
        }
    }

} sampSendChat;
 
  • Нравится
Реакции: Vintik
Решение
вроде сделал всё как требуется, плагин компилируется, но в игре ничего не происходит
возможно я чего-то в упор не вижу, оставлю ссылку если кто-нибудь захочет взглянуть на проект

буду пробовать GetTickCount
скомпилил, всё нормально
1593685582593.png


что я делал: залил либы в отдельную папку cpp/libs. скачал эти либы:
- https://github.com/BlackKnigga/Yet-another-hook-library
- https://github.com/BlackKnigga/coro_wait
- https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.7z, тут подробей.
разорхивируешь всю папку куда угодно, запускаешь bootstrap.bat. если появился b2.exe, то запускай cmd и вводи команду:
Bash:
b2...

imring

Ride the Lightning
Всефорумный модератор
2,361
2,546
Разработчики, только перешедшие с клео\луа на C++ негодуют из-за необходимости использовать разного рода таймеры и лапшу из GetTickCount'ов вместо полюбившихся функций wait. Но особо ярых фанатов клео это не устраивает, отчего они начинают использовать потоки ради функций вроде Sleep для того чтобы не блокировать цикл игры. Однако это не безопасно. Функции ни GTA ни SAMP'а абсолютно не предназначены для использования в разных потоках и их использование может привести к рандомным крашам.
 
  • Нравится
Реакции: Vintik и AnWu
D

deleted-user-204957

Гость
всем привет

предпринимая очередную попытку пофиксить краши https://www.blast.hk/threads/56447/, наткнулся на проблемную часть: отправку результата распознавания в чат без использования сторонних api

я выделил этот момент в отдельный файл, собственно мой вопрос: что я делаю не так и как заставить SendChat() работать так же стабильно, как и AddMessage()

C++:
#include <Windows.h>
#include <vector>
#include <iostream>
#include <string>
#include <cstring>

class sampSendChat {
private:
    HANDLE hThread = NULL;

public:
    sampSendChat() {
        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sampSendChat::init, (LPVOID)this, 0, (LPDWORD)NULL);
    }

    ~sampSendChat() {
        TerminateThread(hThread, 0);
    }

    static LPVOID WINAPI init(LPVOID* lpParam) {
        sampSendChat* sender = (sampSendChat*)lpParam;
        sender->run();

        sender->hThread = NULL;

        return NULL;
    }

    void AddMessage(const std::string& string, int color)
    {
        typedef int(__thiscall* AddMessage)(DWORD, int, const char*, int, int, int);
        static AddMessage addMessage = (AddMessage)((DWORD)GetModuleHandle("samp.dll") + 0x64010);
        static DWORD chatPointer = (DWORD)GetModuleHandle("samp.dll") + 0x21A0E4;

        addMessage(*(DWORD*)chatPointer, 4, string.c_str(), 0, color, 0);
    }



    void SendChat(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        /*
        какой-нибудь способ конвертировать std::string -> const char*, чтобы оно не крашило через n повторений
        */

        if (text[0] == '/')
            sendCommand(cstr);
        else
            sendText(cstr);
    }


    /*крашит через 189 раз*/
    void SendChat1(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        if (text[0] == '/')
            sendCommand(text.c_str());
        else
            sendText(text.c_str());
    }

    /*крашит через 758 раз*/
    void SendChat2(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        char* cstr = new char[text.length() + 1];
        std::strcpy(cstr, text.c_str());

        if (text[0] == '/')
            sendCommand(cstr);
        else
            sendText(cstr);
        delete[] cstr;
    }

    std::vector<char> toVector(const std::string& s) {
        std::vector<char> v(s.size() + 1);
        memcpy(&v.front(), s.c_str(), s.size() + 1);
        return v;
    }

    /*крашит через 215 раз*/
    void SendChat3(const std::string& text)
    {
        typedef int(__stdcall* SendCommand)(const char*);
        typedef int(__stdcall* SendText)(const char*);
        static SendCommand sendCommand = (SendCommand)((DWORD)GetModuleHandle("samp.dll") + 0x65C60);
        static SendText sendText = (SendText)((DWORD)GetModuleHandle("samp.dll") + 0x57F0);

        std::vector<char> v = toVector(text);

        if (text[0] == '/')
            sendCommand(v.data());
        else
            sendText(v.data());

        v.clear();
    }


    void run() {
        Sleep(15000);

        while (true)
        {
            Sleep(100);

            SendChat("test");

            static int counter = 0;
            counter++;

            AddMessage("message sent. Times: " + std::to_string(counter), -1);
        }
    }

} sampSendChat;
 

qrlk

Известный
Автор темы
Друг
411
926
вроде сделал всё как требуется, плагин компилируется, но в игре ничего не происходит
возможно я чего-то в упор не вижу, оставлю ссылку если кто-нибудь захочет взглянуть на проект

буду пробовать GetTickCount
 

imring

Ride the Lightning
Всефорумный модератор
2,361
2,546
вроде сделал всё как требуется, плагин компилируется, но в игре ничего не происходит
возможно я чего-то в упор не вижу, оставлю ссылку если кто-нибудь захочет взглянуть на проект

буду пробовать GetTickCount
скомпилил, всё нормально
1593685582593.png


что я делал: залил либы в отдельную папку cpp/libs. скачал эти либы:
- https://github.com/BlackKnigga/Yet-another-hook-library
- https://github.com/BlackKnigga/coro_wait
- https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.7z, тут подробей.
разорхивируешь всю папку куда угодно, запускаешь bootstrap.bat. если появился b2.exe, то запускай cmd и вводи команду:
Bash:
b2 variant=release address-model=32 --with-context toolset=msvc link=static
стат. либа будет в boost\stage\lib
- https://github.com/BlastHackNet/SAMP-API, тут надо скомпилить стат. либу.
на всякий проверяй, одинаковые конфигурации у либы и у твоего проекта (release/debug).
 

Вложения

  • coro_wait_example.zip
    4 KB · Просмотры: 84
  • Нравится
  • Влюблен
Реакции: AnWu, shinoa и qrlk