I am working on network programming using epoll and I have this code.
int str_len = read(m_events[i].data.fd, buf, BUF_SIZE);
printf("read %d \n", str_len);
if(str_len == 0){
if(!removeClient(m_events[i].data.fd))
break;
close(m_events[i].data.fd);
}
else {
printf("ServerManager::eventAcceptLoop, A message has been received \n");
pushWork(buf);
}
the buf is declared like this
buf[BUF_SIZE];
and I want to pass the data in the buf to the functiion "pushWork"
pushWork(char * pdata){
hand this pdata to the thread pool to parse and handle it
}
I think I need to copy the data in the buf instead of pointing to the buf because it will be overriden whenever a new data comes in. Right now I do something like
char *pdata = buf;
pushWork(pdata)
Should I do memcopy or something else? and flush the buf?
Please let me know how I can handle this. Thanks in advance...
Yes, you can copy the data:
char* pdata = new char[str_len];
memcpy(pdata, buf, str_len);
pushWork(pdata);
At the pushWork end, it has to take care of freeing the data when it's done:
delete[] pdata;
You will also want to consider encapsulating this all into a std::vector so you don't have to worry about exception safety:
std::vector<char> data(buf, buf + str_len);
pushWork(data);
In this case, pushWork needs to be modified to take a std::vector by value, but the upside is that it won't have to worry about deleting the data when done, and will be fully exception-safe.
Related
To read data from a file, I create heap memory then pass the variable pointer to a function so fread() will put the file data into the pointer. But when the function returns, there is no data in the new created memory.
int main(...) {
MyFile File;
File.Open(...);
int filesize = File.Tell();
char* buffer = new buffer[filesize]; // Create some memory for the data
File.Read((char**)&buffer);
// Now do something with the buffer. BUT there is trash in it.
File.Close();
delete [] buffer;
}
size_t File::Read(void* buf) {
...
::fseek(fStream, 0, SEEK_END);
int fileSize = ::ftell(fStream); // Get file size.
::fseek(fStream, 0, SEEK_SET);
::fread(buf, 1, fileSize, fStream);
return (fileSize);
}
Yes, I can put char * myBuffer = new char[fileSize]; inside of File::Read(...) before ::fread(myBuffer, 1, fileSize, fStream);,
but I should not have to do this because I already have heap memory
(buffer) in main().
You're reading your file contents into the pointer buffer, not the array it points to.
You're overcomplicating things anyway. You don't need a pointer to a pointer, or a void*. You can simply pass a char* to Read. You should really also pass the size of the buffer pointed to into Read as well. Otherwise you risk overflowing your buffer.
int main() {
MyFile File;
File.Open(/*.....*/);
int filesize = File.Tell()
char* buffer = new buffer[filesize]; // Create some memory for the data
File.Read(buffer, filesize);
// Now do something with the buffer. BUT there is trash in it.
File.Close();
delete [] buffer;
}
size_t File::Read(char* buf, size_t count) {
// ......
// No need to find the size of the file a second time
// Return the actual number of bytes read
return ::fread(buf, 1, count, fStream);
}
I changed my function to:
size_t nvFile::Read( char * pszBuffer, const size_t uiCount ) ...
Thank you Miles Budnek! I did not think enought of my problem. I am opening a binary file and it is a byte (char), so it not have to be void *. (I put on my 'cone-of-shame' for not thinking.)
Thank you for help and makeing me think more. :)
I need to copy buffer (for undo states) before making changes.
So, the classic code looks like:
byte *buf = NULL;
byte *oldbuf = NULL;
buf = new byte[100];
//do something with buf
//Here I need to copy "buf" to "oldbuf"
oldbuf = new byte[100];
memcpy(oldbuf, buf, 100);
delete[]buf;
buf = new byte[50];
//next do some with buf
It's works fine, but take some time for "memcpy".
Can I copy buffer by pass pointer? Somethink like this?:
byte *buf = NULL;
byte *oldbuf = NULL;
buf = new byte[100];
//do something with buf
//Here I need to copy "buf" to "oldbuf"
oldbuf = buf;
buf = new byte[50];
//next do some with buf
I need to copy buffer (for undo states) before making changes. So, the classic code looks like: ...
No, the classic c++ code to use ever looked like
std::vector<byte> buf(100);
//do something with buf
//Here I need to copy "buf" to "oldbuf"
std::vector<byte> oldbuf = buf;
buf = std::vector<byte>(50);
//next do some with buf
That was working even before the 1st c++ standard was released.
Of course std::vector<byte> oldbuf = buf; involves to copy the contents sequentially, which takes some time. If there's any optimization to do this using HW capabilities, you should be faithful that the compiler will emit the necessary instructions to do that.
For the current c++ standard you could use std::move() to avoid making a copy of the original buf:
std::vector<byte> oldbuf = std::move(buf);
buf = std::vector<byte>(50);
You would be copying the reference and not the contents at that memory location. Buf as it is, is simply a reference.
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.
I know this kind of question has already been asked. I also used the solution of this topic to my tests. However, I want to know how using this kind of function without memory leak neither exception.
Note:
LPTSTR ~ char* and
LPCTSTR ~ const char*
void add_to_buffer(LPTSTR* buffer, LPCTSTR msg) {
// Determine new size
int newSize = 0;
// Allocate new buffer
if (*buffer == NULL)
newSize = _tcsclen(msg) + 1; // strlen()
else
newSize = _tcslen(*buffer) + _tcsclen(msg) + 1;
LPTSTR newBuffer = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newSize); // malloc()
// Do the copy and concat
if (*buffer == NULL)
_tcscpy(newBuffer, msg); // strcpy()
else
{
_tcscpy(newBuffer, *buffer);
_tcscat(newBuffer, msg); // strcat()
// release old buffer
HeapFree(GetProcessHeap(), 0, *buffer); // free()
}
// store new pointer
*buffer = newBuffer;
}
Tests:
LPTSTR test = NULL;
add_to_buffer(&test, _T("User:\r\n"));
add_to_buffer(&test, _T("42"));
First call to add_to_buffer works. However, the second function call causes an exception at HeapFree. I'm sure this is a problem about pointers, but I do not understand how to fix it.
Is it a good method? How to fix my exception?
If you are compiling the code as multi-byte application this line
LPTSTR newBuffer = (LPTSTR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
newSize
);
might allocate to few memory.
To fix this use:
LPTSTR newBuffer = (LPTSTR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
newSize * sizeof(*newBuffer)
);
Besides this and the fact that the code lacks error checking for system calls the code looks fine.
However, to simplify things one can use HeapReAlloc() instead of the combination of HeapAlloc() and HeapFree().
If the program crashes anyway this might due to the memory management already being mashed up before this actual crash you observe.
If your program is unicode-enabled, you're not allocating enough memory - because string length (in symbols) and string size (in bytes) don't match.
If it isn't, I don't see reason of using non-standard-C types over standard ones. It shouldn't be a problem though.
I am using a tcp server that I wrote for handling inputs into a database. I have a tcp client sitting on a server that sends the filename to a tcp server sitting on a different linux server. once the filename is received the linux server goes into a shared folder and pulls the file then inserts it into the database.
my problem is with correctly declaring the buffer and clearing it to make sure I get the correct filename without any gibberish added or anything removed from it.
right now it is working like this:
char data[1024];
which is fine but it does not automatically delete the buffer completely, so i tried to implicitly allocate memory to "data" such as:
char *data = (char*) malloc(1024 * sizeof(char));
...
free(data);
OR
char *data = new char[1024];
...
delete[] data;
For some reason the above two declaration are declaring a buffer of size =8 I got this using
sizeof(data);
also what I am receiving is only 8 characters long. I am not sure why it is doing this, any help??
EDIT
char *data = (char*)malloc(1048 * sizeof(char));
if(data==NULL) exit(1);
cout << "DATA Size: " << sizeof(data) << "\n";
int msglen = read(conn, data, sizeof(data));
cout << "Server got " << msglen << " byte message: " << data << "\n";
if(write(conn, &msglen, sizeof(msglen))<0){
cout << "Failed to write back to the client " << strerror(errno);
}
free(data);
close(conn);
There are several things wrong with your code.
1) dont use malloc - you flagged your question as c++ - use malloc only when necessary replace it with:
const int dataSize = 1024;
char *data = new char[dataSize];
2) sizeof(data) when data is char* returns 8 because it returns size of a pointer not an array when you declare data as array sizeof will return bytes occupied by whole array. you should replace you read with:
int msglen = read(conn,data,dataSize)
3) I assume that u want to write data u've just received back to sender.. Then:
in write function you put sizeof(msglen) as third argument which will (mostly) always return 4. remove sizeof( ).
write(conn, data, msglen);
after you are done with the data dont forget to clear the memory using:
delete[] data;
use delete[] always when you assigned memory with new[].
API write(int socket, char *buf, int len);
Code becomes this:
write(con, data, msglen);
Assuming you can't use the stack (e.g. char buf[1024]), using naked pointers is discouraged as bad style and bug prone. Instead, use RAII and some variant of amanged memory, such as shared_ptr or unique_ptr.
#include <memory> and use a std::shared_ptr<>, or std::unique_ptr<> plus std::move() to return the buffer:
std::size_t bufSize = 1024;
std::unique_ptr<char[]> myUniqueBuf(new char[bufSize]);
ssize_t msglen = ::read(conn, *myUniqueBuf, bufSize); // return type is ssize_t, not int
return std::move(myUniqueBuf); // If you need to return the buffer
// I think you will probably prefer a shared_ptr<> because it has a copy
// constructor which makes it easier to pass around and return from functions
std::shared_ptr<char[]> mySharedBuf(new char[1024]);
ssize_t msglen = ::read(conn, *mySharedBuf, bufSize); // return type is ssize_t, not int
ssize_t bytesOut = ::write(conn, *mySharedBuf, msglen);
return mySharedBuf;
The advantage to std::shared_ptr or std::unique_ptr is that you don't have to worry about cleaning up a naked pointer (i.e. calling delete[] data;) because with managed memory it will happen automatically for you when the buffer handle goes out of scope or the reference count goes to zero (e.g. myUniqueBuf or mySharedBuf).