Okay, maybe I'm doing something fatally stupid, but I'm mad. All day I've been dealing with vectors storing in them pointers to my own class, but they mess up (much of the time). Sometimes when I traverse through them, I end up getting the other vector's variable, other times I get some complete nonsense from memory.
Here's some of the code:
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);
Basically, I'm not getting the memory I want. I'm considering going to arrays, or making my own class, but I wanted dynamic storage. This is silly, though...
robots.push_back(robot1);
clients.push_back(client1);
As an example:
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
The TCPClientProtocols are derived from a listening server socket that returns sockets and puts them into the class. While the pointers sit inside the vectors, I use socket functions in the class, i.e
robot->sendData(buffer, lenght);
robot->receiveData(buffer, length);
etc. Afterwards, I go try to reference them again. I can't put all the code here... it's over 500 lines long.
Then I collect the robot names, and I either get gibbrish, or the client's name. Anyway, thanks for your help.
EDIT: I deliberately tested it to see exactly what it was doing at every step. It printed out the exact name/string (robot->name) that I wanted. After it was pushed into the vector, however, I took that exact same pointer from within the vector, it no longer pointed to the right name, instead gave me something else entirely. That's why I'm confused. My apparently bad memory manipulation works well enough when vectors aren't involved.
The function that adds directly to the vector:
void addRobotToList(TCPClientProtocol *robot){
//add robot to list
robots.push_back(robot);
cout<<"Added "<<robot->name<<endl;
}
The function that calls this function (warning: long!) - and yes, I mean to divide it up but this is sort of a draft:
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;
}
You code is a horrible mix of C and C++ and of course all the errors are in the C parts :). So don't blame vectors but instead look at all that horrible low level memory manipulation.
Looks to me that
There's no guarantee that you won't overflow the bounds of list
There's no guarantee that list will be null terminated
The list memory leaks
Start using std::string would seem to be the best advice.
Some of the things to point out with one look at the code here will be:
You should be using new instead of malloc.
You should be using smart pointers not storing raw pointers in your vector.
Use iterators for iterating over the vector contents.
Use std::string and not char*
SOLVED: The error was deleting the loginInfo struct lead to erasing the name object inside of it, thus invalidating the pointers in the name variable. Thanks to all who recommended using strings, they definitely solved the problem and they're not as risky to use.
Related
I am trying to implement parts of a Linux based network Tic-Tac-Toe program into a Winsock server program. I am having some issues as the Linux version opens a socket as in integer variable:
int client_sock = 0; however, in the Winsock application a Csocket object is created: m_pClientSocket = new CSocket();
Now obviously when I try to compile the function that sends the players move to the server:
if (!SendStatus(client_sock, MOVE)) {
ServerDisconnected();
}
I get an invalid variable type error as the function is expecting an int and it's receiving a Csock object.
My question is how do I get the functions to work? I have tried getting the socket handle and using that but I'm not sure if that's the right direction and using this SendStatus(this->m_pClientSocket->GetSocketHandle(), WIN); is giving me issues as it's a static function.
Send Status Function:
bool SendStatus(int socket, StatusCode status)
{
char* data = (char*)&status;
size_t left = sizeof(status);
ptrdiff_t rc;
while (left)
{
rc = send(socket, data + sizeof(status) - left, left, 0);
if (rc <= 0) return false;
left -= rc;
}
return true;
}
TakeTurn Function:
bool TakeTurn(TTTBoard& board)
{
bool game_over = false;
bool input_good = false;
int row = 0, col = 0;
// Display the board
board.DrawBoard();
while (!input_good)
{
printf("Enter move (row col): ");
// Make sure two integers were inputted
if (scanf_s("%d %d", &row, &col) == 2)
{
if (row < 0 || row > 2)
printf("Invalid row input. Try again.\n");
else if (col < 0 || col > 2)
printf("Invalid column input. Try again.\n");
else if (!board.IsBlank(row, col))
printf("That cell isn't blank. Try again.\n");
else
input_good = true;
}
else
printf("Invalid move input. Try again.\n");
// flush any data from the internal buffers
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
board.PlayerMakeMove(row, col);
cout << "Sending move to server" << endl;
// Send the move to the server
if (!SendStatus(client_sock, MOVE))
ServerDisconnected();
if (!SendInt(client_sock, row))
ServerDisconnected();
if (!SendInt(client_sock, col))
ServerDisconnected();
// Check for win/draw
if (board.IsWon())
{
cout << "YOU WIN!!!!" << endl;
game_over = true;
SendStatus(client_sock, WIN);
}
else if (board.IsDraw())
{
cout << "You tied ._." << endl;
game_over = true;
SendStatus(client_sock, DRAW);
}
return game_over;
}
Hopefully I have shared enough info, I didn't want to bloat the question, thanks!
I've been stuck on an issue with my program and just hoping for any help at this point :(
or guidance towards the right direction. In my code, I'm implenting a mini shell in c++ where the user can pipe 2 or more processes together, yet an issue keeps coming up whenever I execute it. Only the first and last commands actually execute so say I run:
cat b.txt | sort | tail -2
only cat b.txt and tail -2 would execute.
Here is my attempt at the whole program, also referenced to this which helped me tremendously with the setup.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;
//this variable will take in the line of input submitted by the user
char buf[1024];
//PIDs for the two child processes
pid_t pid[300];
//these will be use to check the status of each child in the parent process
int status;
int status2;
int pid_num = 1;
//initializes the pipe
int pipeA[2] = {-1,-1};
int g = 0;
void first_command(int pipeA[], char * command[], bool pipeExists){
if(pipeExists){
dup2(pipeA[1], 1);
close(pipeA[0]);
}
// this will run command[0] as the file to execute, and command as the arg
execvp(command[0], command);
printf("Can not execute FIRST command, please enter a valid command \n");
exit(127);
}
void other_command(int pipeA[], char * command0[], int index){
dup2(pipeA[0], 0);
close(pipeA[1]);
execvp(command0[0], command0);
printf("Can not execute SECOND command, please enter a valid command\n");
exit(127);
}
void main_func() {
//stay inside the loop and keep asking the user for input until the user quits the program
while (fgets(buf,1024,stdin) != NULL){
//initialize a boolean to check if user wants to pipe something, set to false by default until we check with user
bool pipeExists = false;
//initialize this arrays to NULL so anything that store in them gets cleared out.
//these arrays will hold the commands that the user wants to carry out.
char * command[1024] = {NULL, NULL, NULL};
char *command0[1024] = {NULL, NULL, NULL};
char *command1[] = {NULL, NULL, NULL};
char *command2[] = {NULL, NULL, NULL};
char *command3[] = {NULL, NULL, NULL};
char ** my_commands[] = {
command0,
command1,
command2,
command3,
NULL
};
//Important to delete mark the last byte as 0 in our input
buf[strlen(buf) -1] = 0;
//initialize this number to zero to start save the tokens at this index
int index = 0;
//a char * to hold the token saved by strtok
char * ptr;
ptr = strtok(buf, " \"");
//Loop through 'buf' and save tokens accordingly
while(ptr != NULL){
// if the user types exit at any moment, the program will exit gracefully and terminate
if(strcmp( ptr, "exit" ) == 0){
exit(0);
}
//if ptr is equal to | user wants to pipe something and we change pipeExists to true
if(strcmp( ptr, "|" ) == 0){
pipeExists = true;
index= 0;
ptr = strtok(NULL, " ");
}
//enter here while user doesnt want to user pipes
if(!pipeExists){
command[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
//enter here if user want to use pipes
if(pipeExists){
command0[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
g++;
printf("%s %i\n", ptr, g);
}
for (int s = 0; my_commands[s] != NULL; s++) {
cout << command0[s] << " \n" << endl;
}
//if pipes exists then initialize it
if(pipeExists){
pipe(pipeA);
}
//create first child
if ((pid[0] = fork()) == 0) {
//pass in the pipe, commands and pipe to function to execute
first_command(pipeA, command, pipeExists);
}
else if(pid[0] < 0){
//error with child
cerr<<"error forking first child"<<endl;
}
// if pipe exists create a second process to execute the second part of the command
if(pipeExists){
for(int f = 0; my_commands[f] != NULL; f++) {
//create second child
if ((pid[f] = fork()) == 0) {
other_command(pipeA, command0, index);
}
else if(pid[f] < 0){
//error with second child
cerr<<"error forking child "<< pid_num << endl;
}
}
pid_num++;
}
//if the pipe was created then we close its ends
if(pipeExists){
for(int z = 0; z < pid_num; z++) {
close(pipeA[z]);
}
}
//wait for the first child that ALWAYS executes
if ( (pid[0] = waitpid(pid[0], &status, 0)) < 0)
cerr<<"error waiting for first child"<<endl;
//wait for the second child but only if user wanted to created to use piping
if(pipeExists){
for(int j = 1; j < pid_num; j++) {
if ( (pid[j] = waitpid(pid[j], &status2, 0)) < 0){
printf("Status: %d", pid[j]);
cerr<<"error waiting for child " << j <<endl;
}
}
}
pid_num = 1;
}//endwhile
}
The first iteration works flawlessly, how could I make it work until the end of the loop? I tried to track down the problem , initially in this for loop, the server was not waiting for the client response for some reason, so I thought it might be because send() and recv() are in a void function. So, I tried adding one more send() and recv() pair, which should be waiting for the client to answer, but it doesn't work this way.
I noticed that during the very first iteration, it works great, moving on the next one, it's already ruined. I think it does try to use the previous message, so I changed that to an empty array, which didn't work, because it still uses it.
This is the for loop:
for (int i = 0; i < std::atoi(max_round); i++)
{
bet(client1, message, to_client, size);
feldolgoz(message, game_obj, client1);
bet(client2, message, to_client, size);
feldolgoz(message, game_obj, client2);
game_obj.RoundResult();
char next_round[size] = "Irjon valamit kovetkezo korbe lepesert!";
char answer[size];
send(client1, next_round, sizeof(next_round), 0);
if (recv(client1, &answer, size, 0) < 0)
{
Receive_Error obj;
throw obj;
}
send(client2, next_round, sizeof(next_round), 0);
if (recv(client2, &answer, size, 0) < 0)
{
Receive_Error obj;
throw obj;
}
bzero(answer, sizeof(answer));
}
this is the bet function:
void bet(int client, char *message, char *to_client, const int size)
{
int stuff = send(client, to_client, sizeof(to_client), 0);
if (stuff < 0)
{
Send_Error obj;
throw obj;
}
if (recv(client, message, sizeof(message), 0) < 0)
{
Receive_Error obj;
throw obj;
}
and this is the feldolgoz function (which mainly processes the information):
void feldolgoz(char *message, Roulette &obj, int client)
{
char *temp;
char *word;
char color = 0;
int count = 0;
int money = 0;
int number = -1;
temp = strtok(message, " ");
while (temp != NULL)
{
word = temp;
switch (count)
{
case 0:
color = word[0];
break;
case 1:
number = (int)word[0];
break;
case 2:
color = std::atoi(word);
break;
}
count++;
temp = strtok(NULL, " ");
}
obj.getBet(color, number, money, client);
bzero(message, sizeof(message));
}
The obj.getBet() function basically sends a message to the client whether he won or lost the round, but I highly doubt that is the culprit.The interesting part is , that the first iteration works flawlessly, how could i make it work until the end of the loop?
I'm having problems with getting winsock RIO working.
It seems that every time I post a RIOReceive it returns immediately with 0 bytes transferred, and my peer can't get a message through.
After posting a RIOReceive, I wait on the RIODequeCompletion, which deques immediately with numResults = 1, but when I inspect the bytesTransferred of the RIORESULT struct, it's 0. This tells me that I'm not setting this thing up properly, but I can't find docs or examples that tell me what else I should be doing.
The internet seems to have very little on RIO. I've looked through MSDN, Len Holgate with TheServerFramework, this site, and two GitHub RIO servers.
RIOEchoServer and RIOServer_sm9 are on GitHub, but I can't post more than two links (this is my first question on this site).
This code is just to get things proven. It's currently not set to use the sendCQ, doesn't handle errors well, etc...
Here's the prep work:
void serverRequestThread() {
//init buffers
//register big buffers
recvBufferMain = rio.RIORegisterBuffer(pRecvBufferMain, bufferSize);
sendBufferMain = rio.RIORegisterBuffer(pSendBufferMain, bufferSize);
if (recvBufferMain == RIO_INVALID_BUFFERID) {
cout << "RIO_INVALID_BUFFERID" << endl;
}
if (sendBufferMain == RIO_INVALID_BUFFERID) {
cout << "RIO_INVALID_BUFFERID" << endl;
}
//create recv buffer slice
recvBuffer1.BufferId = recvBufferMain;
recvBuffer1.Offset = 0;
recvBuffer1.Length = 10000;
//create send buffer slice
sendBuffer1.BufferId = sendBufferMain;
sendBuffer1.Offset = 0;
sendBuffer1.Length = 10000;
//completion queue
recvCQ = rio.RIOCreateCompletionQueue(CQsize, NULL);
sendCQ = rio.RIOCreateCompletionQueue(CQsize, NULL);
if (recvCQ == RIO_INVALID_CQ) {
cout << "RIO_INVALID_CQ" << endl;
}
if (sendCQ == RIO_INVALID_CQ) {
cout << "RIO_INVALID_CQ" << endl;
}
//start a loop for newly accept'd socket
while (recvCQ != RIO_INVALID_CQ && sendCQ != RIO_INVALID_CQ) {
//get accept'd socket
struct sockaddr_in saClient;
int iClientSize = sizeof(saClient);
acceptSocket = accept(listenSocket, (SOCKADDR*)&saClient, &iClientSize);
if (acceptSocket == INVALID_SOCKET) {
cout << "Invalid socket" << endl;
printError();
}
//register request queue
requestQueue = rio.RIOCreateRequestQueue(
acceptSocket, //socket
10, //max RECVs on queue
1, //max recv buffers, set to 1
10, //max outstanding sends
1, //max send buffers, set to 1
recvCQ, //recv queue
recvCQ, //send queue
pOperationContext //socket context
);
if (requestQueue == RIO_INVALID_RQ) {
cout << "RIO_INVALID_RQ" << endl;
printError();
}
I now post a RIOReceive:
//start a loop to repin recv buffer for socket
while (acceptSocket != INVALID_SOCKET) {
//pin a recv buffer to wait on data
recvSuccess = rio.RIOReceive(
requestQueue, //socketQueue
&recvBuffer1, //buffer slice
1, //set to 1
RIO_MSG_WAITALL, //flags
0); //requestContext
if (recvSuccess == false) {
cout << "RECV ERROR!!!!!!!!\n";
printError();
}
//wait for recv to post in queue
//std::this_thread::sleep_for(std::chrono::milliseconds(3000));
As soon as I call RIODequeCompletion, it returns 1:
numResults = 0;
while (numResults == 0) numResults = rio.RIODequeueCompletion(recvCQ, recvArray, 10);
if (numResults == RIO_CORRUPT_CQ) {
cout << "RIO_CORRUPT_CQ" << endl;
} else if (numResults == 0) {
cout << "no messages on queue\n";
} else if (numResults > 0) {
but when I inspect the bytesTransferred of the RIORESULT, it's always 0:
if (recvArray[0].BytesTransferred > 0) {
//process results
if (pRecvBufferMain[0] == 'G') {
//set respnose html
strcpy(pSendBufferMain, responseHTTP);
sendSuccess = rio.RIOSend(
requestQueue, //socketQueue
&sendBuffer1, //buffer slice
1, //set to 1
0, //flags
0); //requestContext
} else if (pRecvBufferMain[0] == 'P') {
//process post
} else {
//recv'd a bad message
}
} //end bytesTransferred if statement
//reset everything and post another recv
}//end response if statement
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}//end while loop for recv'ing
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}//end while loop for accept'ing
}// end function
Like I said, I'm probably not using RIOReceive correctly, and/or I'm not setting the correct socket options that I need to (none right now).
I appreciate any help with this.
Try removing RIO_MSG_WAITALL. There may be a bug whereby you're only getting the close notification (bytes == 0) rather than getting a completion with the data in it. Either way it would be interesting to see if the code works without the flag.
Do my example servers and tests work on your hardware?
I encountered a similar issue of having zero bytesReceived in my dequeued completion result while using RioReceive with RioNotify and RioDequeueCompletion. I would also see the 'Status' value of WSAEINVAL (Invalid Parameter = 10022) in my dequeued completion result, this seems to indicate the WSA error code for the Receive call.
The particular reason I had the error is because I had allocated memory for a receiveBuffer and I was trying to pass that buffer pointer as my buffer handle in the RIO_BUFFER_SEGMENT given to RioReceive instead of passing the IntPtr returned by RioRegisterBuffer.
I fully blame myself for using too many untyped IntPtrs and losing type checking. :)
I am writing a file explorer application in Qt C++ and have a libUSB function (QList UsbDevice::getDeviceList()) which gets all attached USB devices, checks each one for my products vendor and product ID's, claims them and the returns them in an array. This all works fine and I get the device I want, however I have added a refresh button which should update the device list shown in a drop-down list (it basically calls the getDeviceList function again) but it seg faults when calling:
int numDevices = libusb_get_device_list(NULL, &usbDevices);
the second time around and I can't for the life of me see why. If someone could check over the code below and see if I have missed something stupid that would be very helpful.
QList<UsbDevice*> UsbDevice::getDeviceList()
{
unsigned char manf[256] = {'\0'};
QList<UsbDevice*> usbDeviceList;
libusb_device **usbDevices;
struct libusb_device_descriptor desc;
int numDevices = libusb_get_device_list(NULL, &usbDevices);
if(numDevices < 0)
{
libusb_free_device_list(usbDevices, 1);
return usbDeviceList;
}
QString error;
for(int i=0; i!=numDevices; ++i)
{
libusb_device *dev = usbDevices[i];
libusb_get_device_descriptor(dev, &desc);
if((desc.idVendor != VendorUsbId) && (desc.idProduct != ProductUsbId))
continue;
libusb_device_handle *handle = NULL;
libusb_config_descriptor *conf_desc = NULL;
int result = 0;
result = libusb_open(dev, &handle);
if(result < 0)
{
if(result == -3)
{
}
error = QString(libusb_error_name(result));
continue;
}
int config = 1;
if( handle == NULL)
{
continue;
}
result = libusb_set_configuration(handle, config);
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
result = libusb_get_config_descriptor(dev, 0, &conf_desc);
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
result = libusb_claim_interface(handle, 0);
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
result = libusb_get_string_descriptor_ascii(handle, desc.iProduct, manf, sizeof(manf));
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
UsbDevice *newDevice = new UsbDevice();
newDevice->setDeviceName(QString((char*)manf));
newDevice->setHandle(handle);
usbDeviceList << newDevice;
}
libusb_free_device_list(usbDevices, 1);
return usbDeviceList;
}
You are calling libusb_init() at the beginning of your program, but you are also calling libusb_exit() at the beginning : before calling a.exec().
Your first call probably happens in MainWindow constructor ?
You could instead subclass QApplication, call libusb_init() in the constructor and libusb_exit() in the destructor.