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
Related
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 have this piece of code:
char* mtlBuffer = readFromBinary(myfile[0]);
string mtlBufferStr = mtlBuffer;
if (mtlBufferStr != " ")
{
mtlFile.open(fileLocation + "/" + mtlBufferStr.substr(7));
if (mtlFile.is_open())
{
mtlFile.seekg(0, ios::end);
mtlLength = mtlFile.tellg();
mtlFile.seekg(0, ios::beg);
while (mtlFile.tellg() < mtlLength)
{
mtlFile.getline(mtlBuffer, 255);
mtlBufferStr = mtlBuffer;
}
}
}
on the line:
mtlBufferStr = mtlBuffer;
I got a run time error:
Win32.exe has triggered a breakpoint.
This happens on the malloc file. I have chacked what mtlBuffer stored and its:
"# MTL written from /Users/manapoly/Desktop/Yusup/Models/Land/Lamborghini/Aventador/Aventador/Avent.obj"
The weird this is if I delete this line (and compare mtlBufferStr to the value he needs to contain):
mtlFile.getline(mtlBuffer, 255);
The code perfectly works. Why does getLine fail the program?
Sorry about my English.
The line
mtlFile.getline(mtlBuffer, 255);
looks like it expects a pointer to a pre-allocated byte buffer. And the "255" might specify the size of that buffer.
But I cannot see any allocation done in your code.
So I would say "getline" tries to write into non-allocated space.
This code is the problem.
mtlFile.getline(mtlBuffer, 255);
mtlBufferStr = mtlBuffer;
You need to read into a locally allocated buffer. For example:
char buf[255];
mtlFile.getline(buf, 255);
mtlBufferStr = buf;
mtlBuffer is a pointer to an internal buffer somewhere, and obviously not suitable for reuse. As a general principle, any time you reuse a variable for some different purpose expect a problem of some kind, sooner or later.
I want to parse UTF-8 file to ustring, I read this file in str.
There is an error:
terminate called after throwing an instance of 'Glib::ConvertError'.
What should I do?
char* cs = (char*) malloc(sizeof(char) * str.length());
strcpy(cs, str.c_str());
ustring res;
while (strlen(cs) > 0) {
gunichar ch = g_utf8_get_char(cs);
res.push_back(ch);
cs = g_utf8_next_char(cs);
}
wofstream wout("output");
cout << res << endl;
This looks very wrong:
char* cs = (char*) malloc(sizeof(str.c_str()));
as sizeof(str.c_str()) is bound to give you some small number like 4 or 8 (whichever is the size of a pointer on your machine, as the result of str.c_str().
Of course, it doesn't REALLY matter, since the next line, you are leaking the memory you just allocated incorrectly:
cs = const_cast<char*> (str.c_str());
I'm far from convinced that you need the const_cast<char *> (it is certainly WRONG to do this, since modifying the string inside a string is undefined behaviour).
I'm trying to write to a file and i get a segmentation fault when i delete the allocated memory. I don't understant what is the problem, please help:
void writeToLog(string msg) {
int len = msg.size()+1;
char *text = new char(len);
strcpy(text,msg.c_str());
char* p = text;
for(int i=0; i<len; i++){
fputc(*p, _log) ;
p++;
}
delete[] text; //THIS IS WHERE IT CRASHES
}
I also tried without the [ ] but then i get
*** glibc detected *** ./s: free(): invalid next size (fast): 0x09ef7308 ***
So what is the problem?
Thanks!
This:
char *text = new char(len);
should be:
char *text = new char[len + 1];
And this is all unnecessary anyway. why are you doing it?
Well, delete[] doesn't balance new char(N), it balances new char[N]. The former creates a pointer to a single char and gives it the value N; the latter creates a pointer to an array of char with length N, and leaves the values indefined.
Of course, to write a std::string to a FILE *, why not just do:
fwrite(msg.c_str(), sizeof(char), msg.size() + 1, _log);
Note that preserves the trailing null character; so does your original code.
char *text = new char(len);
allocates just one char. Try with:
char *text = new char[len];
Try this:
char *text = new char[len];
Then:
delete[] text;
Although the technical issue has been answer (mismatched new/delete pair), I still think you could benefit from some help here. And I thus propose to help you trim your code.
First: there would not be any issue if you simply did not perform a copy.
void writeToLog(string msg) {
typedef std::string::const_iterator iterator;
for(iterator it = msg.begin(), end = msg.end(); it != end; ++it) {
fputc(*it, _log) ;
}
}
Note how I reworked the code to use C++ iterators instead of a mix of pointers and indices.
Second: what is this fputc call ?
You should not need to use a FILE* in your code. If you do, you are likely to get it wrong too and forget to close it, or close it twice etc...
The Standard Library provides the Streams collection to handle input and output, and for a log file the ofstream class seems particularly adapted.
std::ofstream _log("myLogFile");
void writeToLog(std::string const& msg) { // by reference (no copy)
_log << msg;
}
Note how it is much simpler ? And you cannot forget to close the file either, because if you do forget, then it'll be closed when _log is destructed anyway.
Of course at this point one might decide that it is superflous to have a function. However such a function allows you to prefix the message, typically with timestamps / PID / Thread ID or other decorations, so it's still nice.
I am trying to get the entire raw header into a file but everytime I attempt to write the contents I get a file full of ÌÌÌÌÌÌÌÌÌÌÌ. What am I doing wrong?
DWORD CTryISAPIFilter::OnPreprocHeaders(CHttpFilterContext* httpContext,
PHTTP_FILTER_PREPROC_HEADERS headerInformation)
{
char buffer[4096];
DWORD bufferSize = sizeof(buffer);
BOOL HeaderBoolean = headerInformation->GetHeader(httpContext->m_pFC, "ALL_RAW", buffer, &bufferSize);
char * ptrIn = (char *) buffer;
std::string postData2 = ptrIn;
char * outputString = new char[4096];
int i = 0;
for(i=0;i<4096;i++){
outputString[i] = postData2[i];
}
outputString[i+1] = NULL;
std::ofstream outfile ("D:\\WebSites\\wwwroot\\test.txt",std::ios::app);
outfile << outputString << std::endl;
outfile.close();
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
Is headerInformation->GetHeader() returning success?
If so, how much is it actually writing into buffer (presumably it tells you this in a value it places in bufferSize)
I suspect that GetHeader() is failing, and nothing is being written to buffer because:
you're getting all "ÌÌÌÌÌÌÌÌÌÌÌ" characters (which is what the debug builds of VC will set uninitialized memory to), and
you're not getting an exception thrown when you index postData2 well past what should usually be the end of the string (in most cases anyway). So there's apparently no '\0' terminator in buffer (which GetHeader() will write if it succeeds).
You need to check for this failure and examine GetLastError() to get more information on what the failure is.
Update: Your buffer might not be large enough. See http://msdn.microsoft.com/en-us/magazine/cc163939.aspx for how to appropriately size the buffer.
Update 2: It's been a while since I've done web stuff, but isn't "ALL_RAW" a CGI-style server environment variable rather than a header? Shouldn't you retrieve this using GetServerVariable() instead of GetHeader()?