gpt4 book ai didi

C++ (Windows) vector 怎么会弄错内存?

转载 作者:太空宇宙 更新时间:2023-11-04 14:57:18 25 4
gpt4 key购买 nike

好吧,也许我正在做一些非常愚蠢的事情,但我很生气。一整天我都在处理存储在它们中的指向我自己的类的指针的 vector ,但它们搞砸了(大部分时间)。有时,当我遍历它们时,我最终会得到另一个 vector 的变量,有时我会从内存中得到一些完全没有意义的东西。

部分代码如下:

vector<TCPClientProtocol*> clients;
vector<TCPClientProtocol*> robots;

//this function gets names from "robots" and sends them to all the "clients"
void sendRobotListToClients(){
//collect the list:
int numRobots = robots.size();
char *list = (char*)malloc(numRobots * USERNAME_SIZE);
for(int i=0; i<numRobots; i++){
int namelen = strlen(robots[i]->name);
memcpy(&list[i*USERNAME_SIZE], robots[i]->name,
namelen);
if(namelen < USERNAME_SIZE)
list[i*USERNAME_SIZE + namelen] = (char)0;
}

//send it to all clients:
int numClients = clients.size();
for(int i=0; i<numClients; i++){
int result = clients[i]->sendRobotList(list, numRobots);
if(result < 0){
cout<<"Failed sending refreshed list to "
<<clients[i]->name<<"."<<endl;
}
}

delete list; //forgot to add this before
}

//How I created vectors:
vector<TCPClientProtocol*> clients;
vector<TCPClientProtocol*> robots;

//and this is how I add to them:
robots.push_back(robot);

基本上,我没有得到我想要的内存。我正在考虑使用数组,或者创建自己的类,但我想要动态存储。但这很愚蠢……

robots.push_back(robot1);
clients.push_back(client1);

举个例子:

TCPClientProtocol *robot = new TCPClientProtocol(mySocket); //create with existing socket
robot->name = "robot1";
cout<<robot->name<<endl; //prints correctly
robots.push_back(robot);
... //do some other stuff (this IS multithreaded, mind you)
cout<<robots[0]->name<<endl; //prints something strange

TCPClientProtocol 派生自监听服务器套接字,该套接字返回套接字并将它们放入类中。当指针位于 vector 内部时,我在类中使用套接字函数,即

robot->sendData(buffer, lenght);
robot->receiveData(buffer, length);

等之后,我再去尝试引用它们。我不能将所有代码都放在这里……它超过 500 行。

然后我收集了机器人的名字,结果要么是乱码,要么是客户的名字。无论如何,感谢您的帮助。

编辑:我特意对其进行了测试,以了解它在每一步都在做什么。它打印出我想要的确切名称/字符串(机器人->名称)。然而,在它被插入 vector 后,我从 vector 中取出了完全相同的指针,它不再指向正确的名称,而是完全给了我别的东西。这就是为什么我很困惑。当不涉及 vector 时,我明显糟糕的内存操作效果很好。

直接与vector相加的函数:

void addRobotToList(TCPClientProtocol *robot){
//add robot to list
robots.push_back(robot);
cout<<"Added "<<robot->name<<endl;
}

调用此函数的函数(警告:长!)- 是的,我的意思是将其分开,但这是一个草稿:

DWORD WINAPI AcceptThread(void* parameter){
TCPClientProtocol* cl = (TCPClientProtocol*)parameter;

TCPHeader *head = new TCPHeader;
loginInfo *logInfo = new loginInfo;

//Read header.
int result = cl->receiveHeader(head);
if(result < 0)
return -1;
//Check data. Expected: DATATYPE_CONNETION_REQUEST
// and check protocol version.
if( head->version != (char)PROTOCOL_VERSION ||
head->type != (char)DATATYPE_CONNECTION_REQUEST ||
head->size != (int)CONNECTION_REQUEST_LENGTH){
goto REJECT;
}

cout<<"Accepted connection."<<endl;

result = cl->requestLoginInfo();
if(result < 0)
goto CONNECTIONLOST;

//Read header.
result = cl->receiveHeader(head);
if(result < 0)
goto CONNECTIONLOST;
if(head->type != DATATYPE_LOGIN_INFO){
goto REJECT;
}

//read login information
result = cl->receiveLoginInfo(logInfo);
if(result < 0)
goto CONNECTIONLOST;

//check for authentication of connector. If failed, return.
if(!authenticate(logInfo)){
goto REJECT;
}

cout<<"Authenticated."<<endl;

//add name to robot/client
cl->name = logInfo->username;

//Check for appropriate userType and add it as a variable:
switch(logInfo->userType){
case USERTYPE_ROBOT:
cl->userType = USERTYPE_ROBOT;
cl->isClient = false;
cout<<"Robot connected: "<<cl->name<<endl;
break;
case USERTYPE_CLIENT:
cl->userType = USERTYPE_CLIENT;
cl->isClient = true;
cout<<"Client connected: "<<cl->name<<endl;
break;
default:
goto REJECT;
break;
}

//Send a phase change to PHASE 2:
result = cl->notifyPhaseChange(2);
if(result < 0)
goto CONNECTIONLOST;

//if client, send robot availability list and listen for errors
// and disconnects while updating client with refreshed lists.
if(cl->isClient){
//add client to clients list:
clients.push_back(cl);

//send initial list:
int numRobots = robots.size();
char *list = (char*)malloc(numRobots * USERNAME_SIZE);
for(int i=0; i<numRobots; i++){
cout<<(i+1)<<" of "<<numRobots<<": "<<robots[i]->name<<endl;
int namelen = strlen(robots[i]->name);
memcpy(&list[i*USERNAME_SIZE], robots[i]->name,
namelen);
if(namelen < USERNAME_SIZE)
list[i*USERNAME_SIZE + namelen] = (char)0;
}
result = cl->sendRobotList(list, numRobots);
if(result < 0){
removeClientFromList(cl->name);
goto CONNECTIONLOST;
}

cout<<"Sent first robot list."<<endl;

//wait to receive a ROBOT_SELECTION, or error or disconnect:
result = cl->receiveHeader(head);
if(result < 0){
removeClientFromList(cl->name);
goto CONNECTIONLOST;
}
if(head->type != DATATYPE_ROBOT_SELECTION){
removeClientFromList(cl->name);
goto REJECT;
}

//receive and process robot selection
char *robotID = (char*)malloc(ROBOT_SELECTION_LENGTH+1);
result = cl->receiveRobotSelection(robotID);
robotID[USERNAME_SIZE] = (char)0;
robotID = formatUsername(robotID);
if(result < 0){
removeClientFromList(cl->name);
goto CONNECTIONLOST;
}

cout<<"Got a selection.."<<endl;

//get the robot and remove it from list
TCPClientProtocol *robot = removeRobotFromList(formatUsername(robotID));
cout<<"Removal win."<<endl;
//check robot status:
if(robot == NULL){
//TRY AGAIN
cout<<"Oh mai gawsh, robot is NULL!"<<endl;
getch();
}
else if(!robot->tcpConnected()){
//TRY AGAIN
cout<<"Oh mai gawsh, robot DISCONNECTED!"<<endl;
getch();
}else{
cout<<"Collected chosen robot: "<<robot->name<<endl;
}

//request stream socket information from client
result = cl->requestStreamSocketInfo();
if(result < 0){
removeClientFromList(cl->name);
addRobotToList(robot); //re-add the robot to availability
goto CONNECTIONLOST;
}

result = cl->receiveHeader(head);
if(result < 0){
removeClientFromList(cl->name);
addRobotToList(robot); //re-add the robot to availability
goto CONNECTIONLOST;
}

//check for datatype
if(head->type != DATATYPE_STREAM_SOCKET_INFO){
removeClientFromList(cl->name);
addRobotToList(robot); //re-add the robot to availability
goto REJECT;
}
//receive stream socket info:
char *ip = (char*)malloc(20);
int port;
result = cl->receiveStreamSocketInfo(ip, &port);
if(result < 0){
removeClientFromList(cl->name);
addRobotToList(robot); //re-add the robot to availability
goto CONNECTIONLOST;
}

cout<<"Got ip: "<<ip<<" port: "<<port<<endl;

//send stream socket information to robot
result = robot->sendStreamSocketInfo(ip, port);
if(result < 0){
//RETURN CLIENT TO 'step 5'
removeClientFromList(cl->name);
delete robot;
goto CONNECTIONLOST;
}

//send phase changes to both, and use this thread
// to monitor signals from client to robot.
result = cl->notifyPhaseChange(3);
if(result < 0){
addRobotToList(robot); //re-add the robot to availability
removeClientFromList(cl->name);
goto CONNECTIONLOST;
}
result = robot->notifyPhaseChange(3);
if(result < 0){
//RETURN CLIENT TO 'step 5'
removeClientFromList(cl->name);
delete robot;
goto CONNECTIONLOST;
}

cout<<"PHASE 3 INITIATED"<<endl;
removeClientFromList(cl->name);

//run a thread sending connections from CLIENT to ROBOT.
while(true){
cout<<"Listening for header..."<<endl;
//read next header from client
result = cl->receiveHeader(head);
cout<<"Got something"<<endl;
if(result < 0){
cout<<"Failed read."<<endl;
delete robot;
goto CONNECTIONLOST;
}
if(head->type != DATATYPE_COMMAND){
cout<<"Not a command. Protocol mismatch"<<endl;
continue;
}

cout<<"Gots header"<<endl;

//read command
result = cl->receiveCommand();
if(result < 0){
//RESET ROBOT!
delete robot;
goto CONNECTIONLOST;
}

cout<<"Got data."<<endl;

result = robot->sendCommand((char)result);
if(result < 0){
//RESET CLIENT!
delete robot;
goto CONNECTIONLOST;
}
}

//spawn a thread for robot-to-client and client-to-robot comm,
// possibly just client-to-robot.
//send a phase change (to phase 3) - in thread!
}

//if robot, add to robot list and wait.
else{
//add robot to robots list:
addRobotToList(cl);
}

delete head;
delete logInfo;
return 0;

//Clean up variables and send reject message
REJECT:
cout<<"Connection rejected."<<endl;
cl->sendRejection();
delete cl;
delete head;
delete logInfo;
return -1;

CONNECTIONLOST:
cout<<"Connection lost."<<endl;
delete cl;
delete head;
delete logInfo;
return -1;
}

最佳答案

你的代码是 C 和 C++ 的可怕混合,当然所有的错误都在 C 部分 :)。所以不要责怪 vector ,而是看看所有那些可怕的低级内存操作。

在我看来

  • 不能保证你不会溢出列表的边界
  • 不保证列表会以空结尾
  • 列表内存泄漏

开始使用 std::string 似乎是最好的建议。

关于C++ (Windows) vector 怎么会弄错内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6992652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com