[英]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_CallBack
和Client
对象已经分配好了。 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.