简体   繁体   English

指向被覆盖的值的指针(访问异常)

[英]Pointer to values getting overwritten (Access exception)

so mine object pointer of a class have some problems and keeps getting overwritten on a function.所以我的 class 的 object 指针有一些问题,并且在 function 上不断被覆盖。 To help you understand, this is a project that is ment to be a library for helping people with easily making winsock socket connections with server from client.为了帮助您理解,这是一个项目,旨在成为一个库,用于帮助人们轻松地从客户端与服务器建立 Winsock 套接字连接。

Main.cpp:主要.cpp:

(includes aleready included)

int main() {

Client client;

//AUTH SERVER
client.WSA_init(2, 2);
SOCKET server_auth = client.init("127.0.0.1", 3211);

std::string auth = client.ClientRecieve(server_auth);
std::string hash = client.Auth(auth);

client.End(server_auth);

client.WSA_init(2, 2);
SOCKET server_main = client.init("127.0.0.1", 3212);

client.ClientSend(server_main, (char*)hash.c_str());

ClientSocketParameters* t_params = new ClientSocketParameters; //Basically a parameter object pointer
t_params->Recv_BufferAccesibilityMode = THREAD_CONSOLE_PRINT_INFO; //These are defined aleready as macros in the win32s.h file
t_params->Recv_Raw = false;
t_params->Recv_Server_Type = SERVER_TYPE_JAVA;
t_params->Send_Mode = THREAD_KEYBOARD_SEND;
t_params->Send_Raw = false;
t_params->Send_Server_Type = SERVER_TYPE_JAVA;

client.setThreadParameters(t_params); //Sets the params

DWORD tid;

ThreadHandler::Socket_CallBack* t_recv = new ThreadHandler::Socket_CallBack;
t_recv->client = &client;
t_recv->socket = server_main;
ThreadHandler::Socket_CallBack* t_send = new ThreadHandler::Socket_CallBack;
t_send->client = &client;
t_send->socket = server_main;

HANDLE h1 = CreateThread(nullptr, NULL, ThreadHandler::ThreadClientRecieve, &t_recv, 0, &tid); //Launches functions that are starting recv and sending with infinity loop (cant put here a client method so needed to do this (btw. these are also in the win32s files))
HANDLE h2 = CreateThread(nullptr, NULL, ThreadHandler::ThreadClientSend, &t_send, 0, &tid);

WaitForSingleObject(h1, INFINITE);
WaitForSingleObject(h2, INFINITE);

client.End(server_main);

return 0;
}

win32_s.h file: win32_s.h 文件:

(includes aleready included)

class ClientSocketParameters { //Parameter class
public:
//Recieving
DWORD Recv_BufferAccesibilityMode;
bool Recv_Raw;
DWORD Recv_Server_Type;
std::string* Recv_StoreAddress;
char* Recv_StoreAdress_Raw;
//Sending
DWORD Send_Mode;
bool Send_Raw;
DWORD Send_Server_Type;
std::string* Send_StoredDataAddress;
};

class Client {
private:

ClientSocketParameters* thread_settings = new ClientSocketParameters; //This is the pointer that is getting overwritten. It is basically a pointer to the parameters that you set with a method in your main

SOCKET init(std::string ip, int port); //Most of these functions are not necessary for problem cause
WSAData WSA_init(int version_makeword_1, int version_makeword_2);
std::string Auth(std::string key);
int PackageManager(); //TODO
int ClientSend(SOCKET dst, char buffer[]);
std::string ClientRecieve(SOCKET src);
std::string BufferToString(char buffer[]);
std::string BufferToJavaString(char buffer[]);
std::string JavaBufferToString(char buffer[]);
int End(SOCKET con);

Some macros

void setThreadParameters(ClientSocketParameters* params);

DWORD WINAPI Thread_ClientRecieve(LPVOID socket_src);
DWORD WINAPI Thread_ClientSend(LPVOID dst);
};

namespace ThreadHandler { //These lauches the thread functions with calling them (check .cpp of this file)
DWORD WINAPI ThreadClientRecieve(LPVOID param);
DWORD WINAPI ThreadClientSend(LPVOID param);

struct Socket_CallBack {
    SOCKET socket;
    Client* client;
};

}

win32_s.cpp file: win32_s.cpp 文件:

#include "win32_s.h"
(I'm not going to show the not necessary functions that work)

void Client::setThreadParameters(ClientSocketParameters* params) {
std::cout << params << std::endl;
thread_settings = params;
std::cout << thread_settings << std::endl; //This address is correct to this point, The Thread_ClientRecieve and the thread send function overwrites the address to 0x11C when checking the variables of the pointer
}

DWORD WINAPI Client::Thread_ClientRecieve(LPVOID lpParam) { //TODO: Packet management, Exceptions

const DWORD MAX_BYTES = 1024;
char buffer[MAX_BYTES];
size_t recvbytes;
SOCKET server = *(SOCKET*)lpParam;

while (true) {

    //std::cout << "here #packet recieve" << std::endl;

    ZeroMemory(buffer, MAX_BYTES);
    
    recvbytes = recv(server, buffer, MAX_BYTES, 0);

    if (recvbytes <= 0) {
        std::cout << "Recieving info from server failed. Cancellig thread..." << std::endl;
        break;
    }

    std::cout << thread_settings->Recv_BufferAccesibilityMode << std::endl;
    std::cout << thread_settings->Recv_Raw << std::endl;
    std::cout << thread_settings->Recv_Server_Type << std::endl;

    if (thread_settings->Recv_BufferAccesibilityMode == THREAD_CONSOLE_PRINT_INFO) {

        std::string console_text;

        if (thread_settings->Recv_Raw) {
            std::cout << buffer << std::endl;
        }
        if (thread_settings->Recv_Server_Type == SERVER_TYPE_JAVA) {
            console_text = JavaBufferToString(buffer);
            std::cout << console_text << std::endl;
        }
        if (thread_settings->Recv_Server_Type == SERVER_TYPE_WINSOCK) {
            console_text = BufferToString(buffer);
            std::cout << console_text << std::endl;
        }
    }

    if (thread_settings->Recv_BufferAccesibilityMode == THREAD_STORE_INFO) {

        std::string buffer_s;

        if (thread_settings->Recv_Raw) {
            thread_settings->Recv_StoreAdress_Raw = buffer;
        }
        if (thread_settings->Recv_Server_Type == SERVER_TYPE_JAVA) {
            buffer_s = JavaBufferToString(buffer);
            *thread_settings->Recv_StoreAddress = buffer_s;
        }
        if (thread_settings->Recv_Server_Type == SERVER_TYPE_WINSOCK) {
            buffer_s = BufferToString(buffer);
            *thread_settings->Recv_StoreAddress = buffer_s;
        }
    }

}

return 0;

}

DWORD WINAPI Client::Thread_ClientSend(LPVOID lpParam) {

const DWORD MAX_BYTES = 1024;
char buffer[1024];
SOCKET server = *(SOCKET*)lpParam;

while (true) {

    //std::cout << "here #send packet" << std::endl;

    if (thread_settings->Send_Mode == THREAD_KEYBOARD_SEND) {
        std::cin.getline(buffer, 1024);
        std::string data;

        if (thread_settings->Send_Raw) {
            if (send(server, buffer, MAX_BYTES, 0) == SOCKET_ERROR) {
                std::cout << "Failed while sending to the server. Closing thread...." << std::endl;
                return -1;
            }
        }

        if (thread_settings->Send_Server_Type == SERVER_TYPE_JAVA) {
            data = BufferToJavaString(buffer);
            if (send(server, data.c_str(), data.size(), 0) == SOCKET_ERROR) {
                std::cout << "Failed while sending to the server. Closing thread...." << std::endl;
                return -1;
            }
        }

        if (thread_settings->Send_Server_Type == SERVER_TYPE_WINSOCK) {
            data = BufferToString(buffer);
            if (send(server, data.c_str(), data.size(), 0) == SOCKET_ERROR) {
                std::cout << "Failed while sending to the server. Closing thread...." << std::endl;
                return -1;
            }
        }

    }

    if (thread_settings->Send_Mode == THREAD_VARIABLE_SEND) {

        if (thread_settings->Send_StoredDataAddress == NULL) {
            std::cout << "Please enter a address to use the thread variable send function. Cancelling thread..." << std::endl;
            return -1;
        }

        //memset(thread_settings.Send_StoredDataAddress, 0x90, sizeof(thread_settings.Send_StoredDataAddress));
        std::string StoredData = *thread_settings->Send_StoredDataAddress;

        if (thread_settings->Send_Server_Type == SERVER_TYPE_JAVA) {
            StoredData.append("\n");

            if (send(server, StoredData.c_str(), StoredData.size(), 0) == SOCKET_ERROR) {
                std::cout << "Failed while sending to the server. Closing thread...." << std::endl;
                return -1;
            }
        }
        else {
            if (send(server, StoredData.c_str(), StoredData.size(), 0) == SOCKET_ERROR) {
                std::cout << "Failed while sending to the server. Closing thread...." << std::endl;
                return -1;
            }
        }
    }
}

}

DWORD WINAPI ThreadHandler::ThreadClientRecieve(LPVOID param) {

Socket_CallBack* s_callback = new Socket_CallBack;
s_callback = (Socket_CallBack*)param;

SOCKET socket = s_callback->socket;

Client* callback_ptr = new Client;
callback_ptr = s_callback->client;

//delete s_callback;
//delete &s_callback->client;

std::cout << "ClientRecvSocketAddr: " << socket << std::endl;
std::cout << "ClientCallBackPtr: " << callback_ptr << std::endl;

return callback_ptr->Thread_ClientRecieve((LPVOID)socket);

}

DWORD WINAPI ThreadHandler::ThreadClientSend(LPVOID param) {

Socket_CallBack* s_callback = new Socket_CallBack;
s_callback = (Socket_CallBack*)param;

SOCKET socket = s_callback->socket;

Client* callback_ptr = new Client;
callback_ptr = s_callback->client;

//delete s_callback;
//delete &s_callback->client;

std::cout << "ClientSendSocketAddr: " << socket << std::endl;
std::cout << "ClientCallBackPtr: " << callback_ptr << std::endl;

return callback_ptr->Thread_ClientSend((LPVOID)socket);

}

This code is not fully done yet so things like checking and smaller details arent still implemented.这段代码还没有完全完成,所以像检查和更小的细节这样的事情还没有实现。 Thanks for any help and using your time at this.感谢您的帮助并在此使用您的时间。

I think the problem is here我认为问题出在这里

SOCKET server_main = client.init("127.0.0.1", 3212);
...
HANDLE h1 = CreateThread(nullptr, NULL, ThreadHandler::ThreadClientRecieve, &server_main, 0, &tid);
HANDLE h2 = CreateThread(nullptr, NULL, ThreadHandler::ThreadClientSend, &server_main, 0, &tid);

You create two threads passing a pointer to a SOCKET as the parameter.您创建两个线程,将指向SOCKET的指针作为参数传递。

But in the thread code you cast that parameter to a Client pointer.但是在线程代码中,您将该参数转换为Client指针。

DWORD WINAPI ThreadHandler::ThreadClientSend(LPVOID param) {
    Client* ptr = (Client*)param;
    return ptr->Thread_ClientSend(param);
}

Not surprisingly casting something that is really a SOCKET* to a Client* isn't going to work.毫不奇怪,将真正是SOCKET*的东西投射到Client*是行不通的。

I guess the code should look like this我猜代码应该是这样的

HANDLE h1 = CreateThread(nullptr, NULL, ThreadHandler::ThreadClientRecieve, &client, 0, &tid);
HANDLE h2 = CreateThread(nullptr, NULL, ThreadHandler::ThreadClientSend, &client, 0, &tid);

EDIT so there are still various issues编辑所以仍然存在各种问题

This code is not wrong, it's just wasteful (and confusing)这段代码没有错,只是浪费(而且令人困惑)

DWORD WINAPI ThreadHandler::ThreadClientRecieve(LPVOID param) {

    Socket_CallBack* s_callback = new Socket_CallBack;
    s_callback = (Socket_CallBack*)param;

    SOCKET socket = s_callback->socket;

    Client* callback_ptr = new Client;
    callback_ptr = s_callback->client;

There's absolutely no need to allocate more memory here, the Socket_CallBack and Client objects have already been allocated.完全没有必要在这里分配更多的 memory, Socket_CallBackClient对象已经分配好了。 This code will work此代码将起作用

DWORD WINAPI ThreadHandler::ThreadClientRecieve(LPVOID param) {

    Socket_CallBack* s_callback =  (Socket_CallBack*)param;
    SOCKET socket = s_callback->socket;
    Client* callback_ptr = s_callback->client;

Now here's the real error现在这是真正的错误

return callback_ptr->Thread_ClientRecieve((LPVOID)socket);

A SOCKET is being passed to Thread_ClientRecieve .一个SOCKET被传递给Thread_ClientRecieve But when we look at Thread_ClientRecieve但是当我们查看Thread_ClientRecieve

DWORD WINAPI Client::Thread_ClientRecieve(LPVOID lpParam) {
    ...
    SOCKET server = *(SOCKET*)lpParam;

The parameter is being cast as a SOCKET* .该参数被转换为SOCKET* When you cast one type to something else, you have to cast back to the same type.当您将一种类型转换为其他类型时,您必须转换回相同的类型。 You can't cast a SOCKET back to a SOCKET* .您不能将SOCKET转换回SOCKET*

Two ways to fix this, one minimal, one the right way to do it (avoiding as much as possible casting and pointers).解决此问题的两种方法,一种是最小的,一种是正确的方法(尽可能避免强制转换和指针)。

The minimal way is to pass the address of the socket, like this最小的方法是传递套接字的地址,像这样

return callback_ptr->Thread_ClientRecieve((LPVOID)&socket);

Now a SOCKET* is being passed to Client::Thread_ClientRecieve , so you can safely cast your parameter back to a SOCKET* .现在SOCKET*正在传递给Client::Thread_ClientRecieve ,因此您可以安全地将参数转换回SOCKET*

But here we can simply remove all the pointers and casting by changing the parameter of Client::Thread_ClientRecieve to be a SOCKET , no casting, no pointers.但是在这里我们可以通过将Client::Thread_ClientRecieve的参数更改为SOCKET来简单地删除所有指针和强制转换,没有强制转换,没有指针。

DWORD WINAPI Client::Thread_ClientRecieve(SOCKET server) {
    ...

and when you call it just pass the socket, no casting needed当你调用它时,只需通过套接字,不需要强制转换

return callback_ptr->Thread_ClientRecieve(socket);

The send code looks to have similar errors.发送代码看起来有类似的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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