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.
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'm trying to base64 decode a string, then convert that value to a char array for later use. The decode works fine, but then I get garbage data when converting.
Here's the code I have so far:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
decodedChar[decodedData.size() + 1] = 0; // terminate the string
for (size_t i = 0; i < decodedData.size(); ++i) {
decodedChar[i] = decodedData[i];
}
vector<BYTE> is a typedef of unsigned char BYTE, as taken from this SO answer. The base64 code is also from this answer (the most upvoted answer, not the accepted answer).
When I run this code, I get the following value in the VisualStudio Text Visualiser:
TestStringÍ
I've also tried other conversion methods, such as:
char* decodedChar = reinterpret_cast< char *>(&decodedData[0]);
Which gives the following:
TestStringÍÍÍýýýýÝÝÝÝÝÝÝ*b4d“
Why am I getting the garbage data at the end of the string? What am i doing wrong?
EDIT: clarified which answer in the linked question I'm using
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
Why would you manually allocate a buffer and then copy to it when you have std::string available that does this for you?
Just do:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
std::string decodedString { decodedData.begin(), decodedData.end() };
std::cout << decodedString << '\n';
If you need a char * out of this, just use .c_str()
const char* cstr = decodedString.c_str();
If you need to pass this on to a function that takes char* as input, for example:
void someFunc(char* data);
//...
//call site
someFunc( &decodedString[0] );
We have a TON of functions and abstractions and containers in C++ that were made to improve upon the C language, and so that programmers wouldn't have to write things by hand and make same mistakes every time they code. It would be best if we use those functionalities wherever we can to avoid raw loops or to do simple modifications like this.
You are writing beyond the last element of your allocated array, which can cause literally anything to happen (according to the C++ standard). You need decodedChar[decodedData.size()] = 0;
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 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.
I am writing two lines in memory using CMemFile::Write():
void CLISTCTRLDlg::Export(LPTSTR *pBlock)
{
CMemFile outMem(32768);
CString csHeader = _T("EmpId EmpName EmpAddress\n");
outMem.Write(csHeader.GetBuffer(0), csHeader.GetLength());
CString csInfo = _T("1 TestName TestAddress\n");
outMem.Write(csInfo.GetBuffer(0), csInfo.GetLength());
long lLen = outMem.GetLength() + 1;
BYTE *mBlock = outMem.Detach();
*pBlock = (LPTSTR) malloc(sizeof(char) * lLen);
memcpy(*pBlock, mBlock, lLen-1);
(*pBlock)[lLen -1] = 0;
OutputDebugStringW(*pBlock);
free(outMem);
}
The output window shows the string "EmpId EmpNam? ???????? ?????????" when the OutputDebugStringW(*pBlock); statement is executed.
I do not understand why the data is truncated.
Further more, the system throws an unhandled exception when the statement free(outMem); is executed.
Can anyone please guide me to the solution and let me know where I am mistaken?
Thanks.
No need to complicate things, to store:
CMemFile file;
CArchive archive(&file, CArchive::store);
CString csHeader = _T("EmpId EmpName EmpAddress\n");
archive << csHeader;
CString csInfo = _T("1 TestName TestAddress\n");
archve << csInfo;
archive.Close();
To load:
file.Seek(0, 0); // rewind the file
CArchive archive(&file, CArchive::load);
CString temp;
archive >> temp;
No need to use memcpy or fiddle with memory.
*pBlock = (LPTSTR) malloc(sizeof(char) * lLen);
memcpy(*pBlock, mBlock, lLen-1);
You appear to be working with wide-character strings everywhere else, but these two calls deal with bytes. They should be:
*pBlock = (LPTSTR) malloc(sizeof(TCHAR) * lLen);
memcpy(*pBlock, mBlock, sizeof(TCHAR) * (lLen-1));
...though as Nikola notes, you're better off if you avoid C-style memory and string manipulation entirely.
Edit: As for the exception when executing free(outMem);... I'm not sure why that even compiles - outMem is your CMemFile object, which is stack-allocated and not a pointer. You should be doing:
free(mBlock); // release memory allocated by, but now detached from CMemFile