In working with the zmq library in C/C++, the following code produces a segmentation fault on the bind command. Using ZMQ v4.2.5 (currently the latest stable release). Below is the relevant code for the connection: creating the context, the socket, and binding the socket (which is the trouble line).
cout << "Creating the context" << endl;
void* ctx = zmq_ctx_new();
if (ctx == NULL)
{
cout << "Context was null!" << endl;
cout << "ZMQ Error code: " << zmq_strerror(zmq_errno()) << endl;
return -1;
}
else cout << "Address of the context: " << ctx << endl;
cout << "Creating the socket now" << endl;
void* socket = zmq_socket(ctx, ZMQ_DEALER);
if (socket == NULL)
{
cout << "Socket was null!" << endl;
cout << "ZMQ Error code: " << zmq_strerror(zmq_errno()) << endl;
return -1;
}
else cout << "Socket created! Address of the socket: " << socket << endl;
const char[] addr = "ipc://test";
cout << "Binding the socket now: " << addr << endl;
int rc = zmq_bind(socket, addr); // <-- SegFault Line
if (rc != 0)
{
cout << "ERROR BINDING THE SOCKET!" << endl;
cout << "ZMQ Error code: " << zmq_strerror(zmq_errno()) << endl;
return -1;
}
else cout << "Socket successfully bound" << endl;
Additional information:
binding the socket works with inproc, but causes the segmentation fault with ipc or tcp
user has appropriate permissions to write to the folder (for ipc sockets)
Valgrind returns a bad permissions for mapped region error in the zmq code pointing at the set_address function
Error still persists if passing in literal string as the argument (as opposed to addr variable)
Running on Centos 7.5 with KDE
Thank you for your time.
Edit: Added OS information in the Additional Information section
Related
I am practicing socket programming. Here is my server code.
Server.cpp
/* UDP Server Sample program*/
#include <Windows.h>
#include <iostream>
#include <winsock.h>
using namespace std;
int main()
{
// Local Variable definitions
cout << "\t\t------- UDP Server---" << endl;
cout << endl;
WSADATA WinSockData;
int iWsaStartup;
int iWsaCleanup;
SOCKET UDPSocketServer;
struct sockaddr_in UDPClient;
char Buffer[512];
int iBufferLen = strlen(Buffer) + 1;
int iBind;
int iReceiveFrom;
int iUDPClientLen = sizeof(UDPClient);
int iCloseSocket;
// STEP-1 Initialization of Winsock
iWsaStartup = WSAStartup(MAKEWORD(2, 2), &WinSockData);
if (iWsaStartup != 0)
{
cout << "WSAStartUp Fun Failed" << endl;
}
cout << "WSAStartUp Success" << endl;
//STEP-2 Fill the UDPClient(SOCKET ADDRESS) Structure
UDPClient.sin_family = AF_INET;
UDPClient.sin_addr.s_addr = inet_addr("169.254.131.8");
UDPClient.sin_port = htons(8001);
// STEP-3 Socket Creation
UDPSocketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketServer == INVALID_SOCKET)
{
cout << "Socket Creation Failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "Socket Creation Success" << endl;
// STEP-4 bind the server
iBind = bind(
UDPSocketServer,
(SOCKADDR*)&UDPClient,
sizeof(UDPClient));
if (iBind == SOCKET_ERROR)
{
cout << "Binding Failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "Binding Success" << endl;
//STEP-5 RecvFrom Fun from receive data from client
while (1)
{
iReceiveFrom = recvfrom(
UDPSocketServer,
Buffer,
iBufferLen,
MSG_PEEK,
(SOCKADDR*)&UDPClient,
&iUDPClientLen);
if (iReceiveFrom == SOCKET_ERROR)
{
cout << "Receiving failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "Receiving Success" << endl;
cout << "Receive Data -> " << Buffer << endl;
}
//STEP-6 CloseSocket Function
iCloseSocket = closesocket(UDPSocketServer);
if (iCloseSocket == SOCKET_ERROR)
{
cout << "Socket Closing failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "Socket CLosing Success" << endl;
//STEP-7 WSACLeanUp Fun for Terminating the use of DLL
iWsaCleanup = WSACleanup();
if (iWsaCleanup == SOCKET_ERROR)
{
cout << "WSA CleanUp failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "WSA CleanUp Success" << endl;
system("PAUSE");
return 0;
}
and this is client code...
client.cpp
/*All right reserved to awinsyspro.com 2019*/
/* UDP Server Sample program*/
#include <Windows.h>
#include <winsock.h>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
cout << "\t\t------UDP Client------" << endl;
cout << endl;
// Local Variable
WSADATA WinSockData;
int iWsaStartup;
int iWsaCleanup;
SOCKET UDPSocketClient;
struct sockaddr_in UDPServer;
// STEP-1 Initialization of Winsock
iWsaStartup = WSAStartup(MAKEWORD(2, 2), &WinSockData);
if (iWsaStartup != 0)
{
cout << "WSAStartup Failed = " << iWsaStartup << endl;
}
cout << "WSAStartup Success" << endl;
// STEP-2 Fill the UDPServer Structure
UDPServer.sin_family = AF_INET;
UDPServer.sin_addr.s_addr = inet_addr("169.254.131.8");
UDPServer.sin_port = htons(8001);
// STEP-3 Socket Creation
UDPSocketClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketClient == INVALID_SOCKET)
{
cout << "Socket Creation Failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "UDP Socket Creation Success" << endl;
int integ = 2656;
//char Buffer[512] = strint;
int iCloseSocket;
while (1)
{
//STEP-4 Sendto Fun.
string strint = to_string(integ);
const char* Buffer = strint.c_str();
int iSendto;
int iBufferLen = strlen(Buffer) + 1;
int iUDPServerLen = sizeof(UDPServer);
cout << integ << endl;
iSendto = sendto(
UDPSocketClient,
Buffer,
iBufferLen,
MSG_DONTROUTE,
(SOCKADDR*)&UDPServer,
sizeof(UDPServer));
if (iSendto == SOCKET_ERROR)
{
cout << "Sending Data Failed " << endl;
cout << "Error No->" << WSAGetLastError() << endl;
}
cout << "Sending Data Success" << endl;
integ = integ + 1;
// STEP-5 CloseSocket Function
}
iCloseSocket = closesocket(UDPSocketClient);
if (iCloseSocket == SOCKET_ERROR)
{
cout << "Socket Closing failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "Close Socket Success" << endl;
// STEP-6 WSACleanUp fun for Terminating the Winsock DLL
iWsaCleanup = WSACleanup();
if (iWsaCleanup == SOCKET_ERROR)
{
cout << "WSA CleanUp failed " << endl;
cout << "Error No-> " << WSAGetLastError() << endl;
}
cout << "Cleanup Success" << endl;
0
system("PAUSE");
return 0;
}
I want to send integer data from the client by an increment of 1 after each loop and receive the respective value on the server side. But I am receiving only the constant integer value "0". I don't know how to do this task.
Thank you
char Buffer[512];
This declares a char array in automatic storage. This char array is completely uninitialized. The next statement:
int iBufferLen = strlen(Buffer) + 1;
This attempts to determine the size of the character string in Buffer, by searching for its terminating \0 byte. That's what strlen() does, after all. It is clear that the intent here is to set iBufferLen to 512, or sizeof(Buffer), instead of to the size of its current string, plus 1, which is obviously incorrect.
Since Buffer is uninitialized, does not contain any character string, and would likely contain random binary garbage, from this point on the shown code is undefined behavior.
If you have not yet learned how to use a debugger, you should consider this to be an excellent opportunity to learn how to do that. If you were to have used your debugger to run your program, one line at a time, your debugger would've immediately shown you that iBufferLen got likely set to 1 or 0, instead of 512.
By attempting to access the TCPSocket inside my "clientArray" I get a Access Violation error. How would I access it properly?
My header file holds the TCPSocket *clientArray.
public:
TCPsocket *clientArray;
SDLNet_SocketSet aSocketSet;
bool serverOn;
It is defined within my constructor:
clientArray = new TCPsocket[maxsockets];
aSocketSet = SDLNet_AllocSocketSet(maxsockets);
It is accessible within another function of mine (it works here without issue):
void ServerSocket::waitingForConnection() {
std::cout << '\r' << flush << "Players connected: " << playersConnected << ". Listening for connection... ";
TCPsocket newsocket = SDLNet_TCP_Accept(serverSocket);
SDL_Delay(1000);
if (!newsocket){
//std::cout << '\r' << flush << "Listening for connection. ";
//std::cout << SDLNet_GetError() << std::endl;
}
else{
std::cout << '\r' << flush << "Socket (client " << slotnum + 1 << ") created successfully. " << std::endl;
clientArray[slotnum] = newsocket;
int n = SDLNet_TCP_AddSocket(aSocketSet, newsocket);
if (n < 0){
std::cout << "Client " << slotnum + 1 << " failed to connect. " << std::endl;
}
else{
char text[10];
std::cout << "Client " << slotnum + 1 << " added to client array successfully." << std::endl;
serverMessage(slotnum, "2 You are successfully connected to the server.");
std::cout << "Sent connection validation to Client " << slotnum + 1 << "." << endl;
std::cout << "Allocating player " << slotnum + 1 << " with player number ." << endl;
serverData(slotnum, '5', slotnum+1);
//ACCESSING IT HERE WITHOUT ISSUE
SDLNet_TCP_Recv(clientArray[slotnum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
slotnum++;
}
//SDLNet_TCP_Close(newsocket);
//SDLNet_TCP_Close(serverSocket);
//code here
}
}
However later on when I try to access it via another function, I get an Access Violation Error :
Unhandled exception at 0x00AED839 in Server.exe: 0xC0000005: Access violation reading location 0x0000000C.
I am calling the problematic function from my Game's Update function as following:
void Game::Update(){
while (g_playersConnected == 2)
{
printGrid();
serverSocket->waitForPlayer((playerTurn-1));
changeTurn();
system("pause");
}
//cout << "Game's Update is running" << endl;
};
This is my other function that is attempting to access the array :
void ServerSocket::waitForPlayer(int playerNum)
{
cout << "Waiting for player " << playerNum + 1 << " (In array : " << playerNum << ")." << endl;
char text[10];
SDLNet_TCP_Recv(clientArray[playerNum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
}
I have not set up Copy constructors or assignment operators and my destructors are just empty blocks at the moment.
ServerSocket::~ServerSocket(){}
Which direction should I go towards solving this issue?
All the best
I'm trying to create a program that will categorize all the connected USB devices and their port GUID.
I found an example of how to get all the information from connected input devices:
#include <windows.h>
#include <iostream>
// Namespace
using namespace std;
// Main
int main()
{
// Program
cout << "USB Device Lister." << endl;
// Get Number Of Devices
UINT nDevices = 0;
GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Any?
if (nDevices < 1)
{
// Exit
cout << "ERR: 0 Devices?";
cin.get();
return 0;
}
// Allocate Memory For Device List
PRAWINPUTDEVICELIST pRawInputDeviceList;
pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices];
// Got Memory?
if (pRawInputDeviceList == NULL)
{
// Error
cout << "ERR: Could not allocate memory for Device List.";
cin.get();
return 0;
}
// Fill Device List Buffer
int nResult;
nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Device List?
if (nResult < 0)
{
// Clean Up
delete[] pRawInputDeviceList;
// Error
cout << "ERR: Could not get device list.";
cin.get();
return 0;
}
// Loop Through Device List
for (UINT i = 0; i < nDevices; i++)
{
// Get Character Count For Device Name
UINT nBufferSize = 0;
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
NULL, // NO Buff, Want Count!
&nBufferSize); // Char Count Here!
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl;
// Next
continue;
}
// Allocate Memory For Device Name
WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];
// Got Memory
if (wcDeviceName == NULL)
{
// Error
cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl;
// Next
continue;
}
// Get Name
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
wcDeviceName, // Get Name!
&nBufferSize); // Char Count
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl;
// Clean Up
delete[] wcDeviceName;
// Next
continue;
}
// Set Device Info & Buffer Size
RID_DEVICE_INFO rdiDeviceInfo;
rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO);
nBufferSize = rdiDeviceInfo.cbSize;
// Get Device Info
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,
RIDI_DEVICEINFO,
&rdiDeviceInfo,
&nBufferSize);
// Got All Buffer?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl;
// Next
continue;
}
// Mouse
if (rdiDeviceInfo.dwType == RIM_TYPEMOUSE)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (MOUSE)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Mouse ID: " << rdiDeviceInfo.mouse.dwId << endl;
cout << "Mouse buttons: " << rdiDeviceInfo.mouse.dwNumberOfButtons << endl;
cout << "Mouse sample rate (Data Points): " << rdiDeviceInfo.mouse.dwSampleRate << endl;
if (rdiDeviceInfo.mouse.fHasHorizontalWheel)
{
cout << "Mouse has horizontal wheel" << endl;
}
else
{
cout << "Mouse does not have horizontal wheel" << endl;
}
}
// Keyboard
else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl;
cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl;
cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl;
cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl;
cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl;
cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl;
}
// Some HID
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
// Delete Name Memory!
delete[] wcDeviceName;
}
// Clean Up - Free Memory
delete[] pRawInputDeviceList;
// Exit
cout << endl << "Finnished.";
cin.get();
return 0;
}
I tried to convert this code to get all the connected USB devices but failed.
So my question is what is the best way to collect the data I'm looking for?
If you want all USB devices, not just "input" devices, then you need to use the same APIs that Device Manager does.
For example, all devices shown by Device Manager can be listed with the help of the SetupDiGetClassDevs function.
For listing USB devices, you'll want to use the enumerator parameter set to "USB" (the enumerator is the bus where the device is attached, for example it can be "PCI", "PCMCIA", "USB" for the main computer busses, and it can also be a secondary bus provided by an expansion device, e.g. "SCSI", "FTDIBUS", and so on). You may sometimes find that you're more interested in child devices than the USB-attached parent device itself.
Keep in mind that it is not enough just to comment // (rdi.dwType == RIM_TYPEHID) as you did in following sequence, since it will print only rdiDeviceInfo.hid.SOMETHING info. If device is not HID, I would expect some junk, or similar to be printed.
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
I would recommend you to add some logging and breakpoints (to print number of devices, to print all device names etc.). If you don't solve it, please paste the code that you use for testing with precise issue explanation.
UPDATE:
GetRawInputDeviceList function
Remarks
The devices returned from this function are the mouse, the keyboard, and other Human Interface Device (HID) devices.
If your device is not HID don't expect to see it in a list.
I have a small program that tries to connect to mongodb and check how many objects it would receive if I could hope to receive objects. In the event, I can't even get a count of objects, and I segfault on cleanup even if I do nothing but connect.
I'm using the GlobalInstance object to maintain my connection and clean up for me at exit. This function I call from main. The program doesn't really do anything else yet.
Any suggestions on what I'm doing wrong that I segfault? Presumably this is related to not being able to call connection->count()?
Many thanks for any pointers.
int foo() {
mongo::client::Options options;
options.setSSLMode(mongo::client::Options::kSSLRequired);
mongo::client::GlobalInstance mongo_connection(options);
mongo::DBClientBase* connection;
if (!mongo_connection.status().isOK()) {
cout << "Mongo connection not established: "
<< mongo_connection.status() << endl;
}
try {
mongo::DBClientConnection c(true);
string error;
ostringstream mongo_url;
mongo_url << "mongodb://" << db_username << ":" << db_password << "#"
<< db_host << ":" << db_port << "/" << db_name;
const mongo::ConnectionString conn_string =
mongo::ConnectionString::parse(mongo_url.str(), error);
if (!conn_string.isValid()) {
cout << "Bad connection string: " << error << endl;
}
// Reality check. Passes.
cout << "user=" << conn_string.getUser() << endl;
cout << "pass=" << conn_string.getPassword() << endl;
cout << "db= " << conn_string.getDatabase() << endl;
const auto servers = conn_string.getServers();
for (const auto& server : servers) {
cout << "serv=" << server << endl;
}
cout << "type=" << conn_string.type() << endl;
// End reality check.
connection = conn_string.connect(error);
cout << "error says: " << error << endl; // Is empty.
cout << "conn=" << connection << endl; // Not zero.
std::cout << "connected ok" << std::endl;
cout << connection->getConnectionId() << endl; // Prints "1".
// This returns an error 13, not authorized, if I included it.
//cout << "count: " << connection->count("focus_groups") << endl;
} catch( const mongo::DBException &e ) {
std::cout << "caught " << e.what() << std::endl;
}
cout << "----------------------------------------------------------------------" << endl;
return 0;
}
/*
Note that I can do this in the mongo shell with no problem:
jeff#siegfried:~ $ mongo my_host:27017/my_db --ssl -u my_user -p
MongoDB shell version: 2.6.3
Enter password:
connecting to: my_host:27017/my_db
> db.focus_groups.count()
26
>
*/
I am running on 64 bit ubuntu 15.04 and compiling with clang 3.6.0. Boost is 1.55 installed via apt-get. The legacy mongo C++ driver I compiled and installed from git at HEAD (861699d116627d63e1c914384a66e4e3ea7c23bc) with ssl support.
This turned out to be a confluence of several things, but at least these two:
When I compiled the legacy driver, the default mode is C++03, which is not binary compatible with C++11 or C++14.
The driver is sensitive to differences in the version of boost with which it and the client using it are compiled.
An extensive thread appears here.
I'm tryning to build a service con gsoap. The code is:
ArchivatorCoreService server;
ArchivatorCoreService *tserver;
int port = 8080;
SOAP_SOCKET m, s;
m = server.bind(NULL, port, 100);
if (!soap_valid_socket(m))
{
exit(1);
}
else
{
qDebug() << "Info: Bind: Succesfully socket connection: " << m << ". Port " << port
}
for (;;)
{
qDebug() << "waiting...";
s = server.accept();
if (!soap_valid_socket(s))
{
if (server.errnum)
{
qDebug() << "1"; << "Error: Failed accept: " << messagec;
exit(1);
}
else
{
qDebug() << "Info: Thread " << i << " accepts socket " << s << " connection from IP " << ((server.ip >> 24)&0xFF) << "." << ((server.ip >> 16)&0xFF) << "." << ((server.ip >> 8)&0xFF) << "." << ((server.ip)&0xFF);
}
qDebug() << "2";
tserver = server.copy(); // make a safe copy
qDebug() << "3";
In line tserver = server.copy(); error sigsegv.
ArchivatorCoreService heracly of soap;
Thanks you very much
You don't say which version of gsoap you are using; however versions prior to 2.8.5 have an issue with memory leaks and SIGSEGVs with the C++ code that is generated. See my previous answer here for a few more details.