Хорошо, возможно я делаю что-то смертельно глупое, но я злюсь.Весь день я имел дело с векторами, хранящими в них указатели на мой собственный класс, но они запутались (большую часть времени).Иногда, когда я прохожу их, я получаю переменную другого вектора, иногда я получаю полную бессмыслицу из памяти.
Вот код:
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
Протоколы TCPClientProtocols получены из сокета прослушивающего сервера, который возвращает сокеты и помещает их в класс.Пока указатели находятся внутри векторов, я использую функции сокетов в классе, т.е.
robot->sendData(buffer, lenght);
robot->receiveData(buffer, length);
и т. Д.После этого я снова попытаюсь сослаться на них.Я не могу поместить весь код здесь ... это более 500 строк.
Затем я собираю имена роботов, и я либо получаю бред, либо имя клиента.В любом случае, спасибо за вашу помощь.
РЕДАКТИРОВАТЬ: Я специально проверил его, чтобы точно увидеть, что он делал на каждом шагу.Он распечатал точное имя / строку (робот-> имя), который я хотел.Однако после того, как он был вставлен в вектор, я взял тот же самый указатель из вектора, он больше не указывал на правильное имя, а дал мне что-то совершенно другое.Вот почему я в замешательстве.Мои явно плохие манипуляции с памятью работают достаточно хорошо, когда векторы не задействованы.
Функция, которая добавляет непосредственно к вектору:
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;
}