Cannot write to MMF using pointer - c++

I would like to write char* buf[] to shared memory.
I got several pointer to several maps - char* m_pP[MAX], maps are opened
m_oMMF[channel] = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, wstring);
m_pP[channel] = (char*) MapViewOfFile(m_oMMF[channel], FILE_MAP_ALL_ACCESS, 0, 0, size);
size of map is big enough, I got int offset where I wanna to write in shared memory using this m_P[] pointer but I am struggling at the syntax of this.
Im not so experienced in C++.
Can anyone help me with this?
Thanks

Not sure If I understood clearly.
But I assume, you have character pointer pointing to mapped memory and you are trying to write data after certain offset.
char * ptr_to_memory = m_pP[channel];
//buf is array of character pointer, so you need to know the "index" as well as "size" of the data you need to write.
char * data_to_write = buf[index];
memcpy( ptr_to_memory + offset, data_to_write, size );
Remember to do some sanity check, whether ( ptr + offset ) is within the mapped region.

Related

How to parse captured packet from socket in cpp?

I'm using RAW socket to capture udp packets. After capturing I want to parse the packet and see what's inside.
The input I get from the socket is an unsigned char* buffer and it's length. I tried to put the buffer into a string but I guess I did it wrong because when I checked the string it was empty.
Any advice?
I don't know what you want to parse, but your have the buffer and it's length. So you can do everything you want with this memory. Look for pointer arithmetic. If you want to make an C-String out of the content, simply add an '\0' to the end of the memory block. But this assumes, that no other 0x00 are inside the buffer. So maybe you have to check that. Like πάντα ῥεῖ said.
Steps:
1: receive UDP package
2: cast like:
unsigned char* buffer;
char* cString = (char*) buffer;
3: check casted cString if an '\0' occurred before buffer size was reached. If it does, then create a new char* pointer to the byte after the '\0', but be aware of the buffer size. Save the pointer in an vector.
I made an code example, but haven't checked if it is runnable!
char* firstPtr = (char*) buffer;
size_t indexer = 0;
std::vector<char*> pointerVec;
pointerVec.push_back(firstPtr);
while(indexer < bufferSize) {
if(*(buffer + indexer) == '\0') {
if(indexer + 1 < bufferSize) {
char* cString = (char*) (buffer + indexer);
pointerVec.push_back(cString);
}
}
} // end while
After that you should have the positions of the different strings saved with the pointers inside of the vector. Now you can handle them to an copy mechanism which takes every C-String pointer and saves it's content to one C-String or String.
Hope you searched for something like that, because you question was unclear.

Store array in C permanantly

Suppose I write a program in C/C++ and create an array of certain size. I want to keep that permanently even if I switch off the computer and later access it. Is there a way to do that? If so do let me know and also after saving it, how to access it.
Save the data to a file and load it on programm start.
Say you create a vector of MAX size for a string:
char * str = (char *) malloc( MAX );
At some point, you fill it with some data:
strcpy( str, "Useful data in the form of a string" );
Finally, at the program's end, you save it to a file:
FILE * f = fopen( "data.bin", "wb" );
fwrite( str, 1, MAX, f );
fclose( f );
At the beginning of the next execution, you'd like to load it:
char * str = (char *) malloc( MAX );
FILE * f = fopen( "data.bin", "rb" );
fread( str, 1, MAX, f );
fclose( f );
This solution has a few shortcomings: for example your data will be only useful for the computer in which you saved it. If you want portability, then you should use text and XML: http://www.jclark.com/xml/expat.html
Hope this helps.
You could use a memory mapped file and use offsets in the memory mapped file in place of pointers. You would have to implement your own dynamic block allocation management in the memory mapped file.
Using offsets would be less efficient than pointers. But you would load and save the data structure in a snap.
It is possible to avoid the use of offset and use real pointers instead. To do this, you save the pointer value to the memory mapped file when you close the memory mapped file. When you load the memory mapped file, you would then have to adjust all pointers in the data structure by adding the offset of the pointer to the memory mapped file.
If the data structure is small, you could do it in one pass when the file is mapped into memory. If the data structure is big, you could do it in a lazy way and only fix pointers of struct when you access them for the first time.

String is not null terminated error

I'm having a string is not null terminated error, though I'm not entirely sure why. The usage of std::string in the second part of the code is one of my attempt to fix this problem, although it still doesn't work.
My initial codes was just using the buffer and copy everything into client_id[]. The error than occurred. If the error is correct, that means I've got either client_ id OR theBuffer does not have a null terminator. I'm pretty sure client_id is fine, since I can see it in debug mode. Strange thing is buffer also has a null terminator. No idea what is wrong.
char * next_token1 = NULL;
char * theWholeMessage = &(inStream[3]);
theTarget = strtok_s(theWholeMessage, " ",&next_token1);
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
Inside sendTalkPackets is. I'm getting a string is not null terminated at the last line.
void ServerGame::sendTalkPackets(char * buffer, unsigned int buffersize, unsigned int theSender, unsigned int theReceiver)
{
std::string theMessage(buffer);
theMessage += "0";
const unsigned int packet_size = sizeof(Packet);
char packet_data[packet_size];
Packet packet;
packet.packet_type = TALK;
char client_id[MAX_MESSAGE_SIZE];
char theBuffer[MAX_MESSAGE_SIZE];
strcpy_s(theBuffer, theMessage.c_str());
//Quick hot fix for error "string not null terminated"
const char * test = theMessage.c_str();
sprintf_s(client_id, "User %s whispered: ", Usernames.find(theSender)->second.c_str());
printf("This is it %s ", buffer);
strcat_s(client_id, buffersize , theBuffer);
Methinks that problem lies in this line:
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
sizeof(next_token1)+1 will always gives 5 (on 32 bit platform) because it return size of pointer not size of char array.
One thing which could be causing this (or other problems): As
buffersize, you pass sizeof(next_token1) + 1. next_token1 is
a pointer, which will have a constant size of (typically) 4 or 8. You
almost certainly want strlen(next_token1) + 1. (Or maybe without the
+ 1; conventions for passing sizes like this generally only include
the '\0' if it is an output buffer. There are a couple of other
places where you're using sizeof, which may have similar problems.
But it would probably be better to redo the whole logic to use
std::string everywhere, rather than all of these C routines. No
worries about buffer sizes and '\0' terminators. (For protocol
buffers, I've also found std::vector<char> or std::vector<unsigned char>
quite useful. This was before the memory in std::string was
guaranteed to be contiguous, but even today, it seems to correspond more
closely to the abstraction I'm dealing with.)
You can't just do
std::string theMessage(buffer);
theMessage += "0";
This fails on two fronts:
The std::string constructor doesn't know where buffer ends, if buffer is not 0-terminated. So theMessage will potentially be garbage and include random stuff until some zero byte was found in the memory beyond the buffer.
Appending string "0" to theMessage doesn't help. What you want is to put a zero byte somewhere, not value 0x30 (which is the ascii code for displaying a zero).
The right way to approach this, is to poke a literal zero byte buffersize slots beyond the start of the buffer. You can't do that in buffer itself, because buffer may not be large enough to accomodate that extra zero byte. A possibility is:
char *newbuffer = malloc(buffersize + 1);
strncpy(newbuffer, buffer, buffersize);
newbuffer[buffersize] = 0; // literal zero value
Or you can construct a std::string, whichever you prefer.

Stack around the variable 'dim'(not an array) was corrupted

I'm trying to read from a binary file, using fstream, some data I have previously written there.
The problem is that after getting to the end of the function the message in the subject is shown
The code is the following:
ifstream in("contrib.bin", ios::in | ios::binary );
char *nume, dim;
in.read((char*)&dim, sizeof(int));
nume = new char[dim + 1];
in.read(nume, dim);
nume[dim] = '\0';
double imp;
in.read((char*)&imp, sizeof(double));
delete [] nume;
Now, I've done my homework and looked for this issue, but the other people who faced it had arrays, whereas my variable is a simple char.
Can someone point me to the right direction, please?
The code
char dim;
in.read((char*)&dim, sizeof(int));
defines a 1 byte char then reads sizeof(int) bytes (which is likely to be greater that 1) into it. This is invalid and may corrupt your stack.
If you need to read sizeof(int) bytes, declare dim as int. Otherwise, change the number of bytes you read to 1. It'd be best if you also used sizeof(dim) to ensure that you only read as many bytes as you've provided storage for:
in.read((char*)&dim, sizeof(dim));
in.read((char*)&dim, sizeof(int)); is not correct, dim only holds sizeof(char) which is one, but you're attempting to read sizeof(int) into it.
All gloves are off after this.
Well you define a character then read in the size of an int. That would be the first issue
char *nume, dim;
in.read((char*)&dim, sizeof(char));

Exception when using strncpy

The following code fragment ends in an exception when executing the strncpy function:
#define MAX_FILENAME_LEN 127
typedef struct {
unsigned long nameLength;
char name[MAX_FILENAME_LEN + 1];
} filestructure;
char *fileName;
strncpy( fileName, filestructure->name, MAX_FILENAME_LEN );
*( fileName + MAX_FILENAME_LEN+1 ) = 0;
Ayone an idea what could go wrong? In the filestructure I have a filename that is 50 characters long so it is within the bounds... I am really a bit lost what could cause the problem in this simple code fragement...
You haven't allocated space for the destination buffer and fileName is uninitialized. So you try to copy somewhere. You should allocate memory and then bother freeing it.
char *fileName = new char[MAX_FILENAME_LEN + 1];
strncpy(...);
*(...) = 0;
doStuffWithTheBuffer( fileName );
delete[] fileName;// free memory
Also if you have a buffer of size N + 1 and want to copy N bytes maximum and null-terminate the buffer you should do
*(buffer + N) = 0;
Your question is tagged C++ but the code is pure C. Why do you do it the hard way? The fact that C string handling isn't all that easy to grasp (and that it isn't all that uncommon to get something wrong once in a while even for programmers who have a good grasp of it) is the very reason C++ let's you do without.
If you're writing C++, do it the C++ way. Use std::string. Honestly, it will spare you many hours of debugging such code.
You haven't allocated space for filename. Either do
filename = malloc (MAX_FILENAME_LEN * sizeof(char));
or
filename = strndup (filestructure->name, MAX_FILENAME_LEN);