Heap Corruption in release mode only - c++

This is a printing thread that prints the statistic of my currently running program
void StatThread::PrintStat(){
clock_t now = 0;
UINT64 oneMega = 1<<20;
const char* CUnique = 0;;
const char* CInserted = 0;;
while((BytesInserted<=fileSize.QuadPart)&&flag){
Sleep(1000);
now = clock();
CUnique = FormatNumber(nUnique);
CInserted = FormatNumber(nInserted);
printf("[ %.2f%%] %u / %u dup %.2f%% # %.2fM/s %.2fMB/s %3.2f%% %uMB\n",
(double)BytesInserted*100/(fileSize.QuadPart),
nUnique,nInserted,(nInserted-nUnique)*100/(double)nInserted,
((double)nInserted/1000000)/((now - start)/(double)CLOCKS_PER_SEC),
((double)BytesInserted/oneMega)/((now - start)/(double)CLOCKS_PER_SEC),
cpu.GetCpuUtilization(NULL),cpu.GetProcessRAMUsage (true));
if(BytesInserted==fileSize.QuadPart)
flag=false;
}
delete[] CUnique; //would have worked with memory leak if commented out
delete[] CInserted; // crash at here! heap corruption
}
This is FormatNumber that returns a pointer to a char array
const char* StatThread::FormatNumber(const UINT64& number) const{
char* result = new char[100];
result[0]='\0';
_i64toa_s(number,result,100,10);
DWORD nDigits = ceil(log10((double)number));
result[nDigits] = '\0';
if(nDigits>3){
DWORD nComma=0;
if(nDigits%3==0)
nComma = (nDigits/3) -1;
else
nComma = nDigits/3;
char* newResult = new char[nComma+nDigits+1];
newResult[nComma+nDigits]='\0';
for(DWORD i=1;i<=nComma+1;i++){
memcpy(newResult+strlen(newResult)-i*3-(i-1),result+strlen(result)-i*3,3);
if(i!=nComma+1){
*(newResult+strlen(newResult)-4*i) = ',';
}
}
delete[] result;
return newResult;
}
return result;
}
What is really weird was that it crashed only in release mode because of a heap corruption, but run smoothly in debug mode. I've already checked everywhere and found no obvious memory leaks, and even Memory Leak Detector said so too.
Visual Leak Detector Version 2.2.3 installed.
The thread 0x958 has exited with code 0 (0x0).
No memory leaks detected.
Visual Leak Detector is now exiting.
The program '[5232] Caching.exe' has exited with code 0 (0x0).
However, when run in release mode,it threw an error that said my program stop working and I clicked on debug, it pointed to the line that caused the heap corruption.
The thread 0xe4c has exited with code 0 (0x0).
Unhandled exception at 0x00000000770E6AE2 (ntdll.dll) in Caching.exe: 0xC0000374: A heap has been corrupted (parameters: 0x000000007715D430).
If I commented out this line, it worked fine but Memory Leak Detector would have complained about memory leak! I don't understand how to cause a heap corruption when there was no memory leaks, (at least that's what the Leak Detector said). Please help, Thank you in advance.
Edit:
Heap corruption was fixed, because in the very last iteration, I still copied 3 byes to the front instead of whatever is leftover. Thank you all for helps!
const char* StatThread::FormatNumber(const UINT64& number) const{
char* result = new char[100];
result[0]='\0';
_ui64toa_s(number,result,100,10);
DWORD nDigits = (DWORD)ceil(log10((double)number));
if(number%10==0){
nDigits++;
}
result[nDigits] = '\0';
if(nDigits>3){
DWORD nComma=0;
if(nDigits%3==0)
nComma = (nDigits/3) -1;
else
nComma = nDigits/3;
char* newResult = new char[nComma+nDigits+1];
DWORD lenNewResult = nComma+nDigits;
DWORD lenResult = nDigits;
for(DWORD i=1;i<=nComma+1;i++){
if(i!=nComma+1){
memcpy(newResult+lenNewResult-4*i+1,result+lenResult-3*i,3);
*(newResult+lenNewResult-4*i) = ',';
}
else{
memcpy(newResult,result,lenNewResult-4*(i-1));
}
}
newResult[nComma+nDigits] = '\0';
delete[] result;
return newResult;
}
return result;
}

Sorry to be blunt, but the code to "format" a string is horrible.
First of all, you pass in an unsigned 64-bit int value, which you formatted as a signed value instead. If you claim to sell bananas, you shouldn't give your customers plantains instead.
But what's worse is that what you do return (when you don't crash) isn't even right. If a user passes in 0, well, then you return nothing at all. And if a user passes in 1000000 you return 100,000 and if he passes in 10000000 you return 1,000,000. Oh well, what's a factor of 10 for some numbers between friends? ;)
These, along with the crash, are symptoms of the crazy pointer arithmetic your code does. Now, to the bugs:
First of all, when you allocate 'newResult' you leave the buffer in a very weird state. The first nComma + nDigits bytes are random values, followed by a NULL. You then call strlen on that buffer. The result of that strlen can be any number between 0 and nComma + nDigits, because any one of the nComma + nDigit characters may contain the null byte, which will cause strlen to terminate prematurely. In other words, the code is non-deterministic after that point.
Sidenote: If you're curious why it works in debug builds, it's because the compiler and the debug version of the runtime libraries try to help you catch bugs by initializing memory for you. In Visual C++ the fill mask is usually 0xCC. This made sure that the bug in your strlen() was covered up in debug builds.
Fixing that bug is pretty simple: simply initialize the buffer with spaces, followed by a NULL.
char* newResult = new char[nComma+nDigits+1];
memset(newResult, ' ', nComma+nDigits);
newResult[nComma+nDigits]='\0';
But there's one more bug. Let's try to format the number 1152921504606846975 which should become 1,152,921,504,606,846,975. Let's see what some of fancy pointer arithmetic operations give us:
memcpy(newResult + 25 - 3 - 0, result + 19 - 3, 3)
*(newResult + 25 - 4) = ','
memcpy(newResult + 25 - 6 - 1, result + 19 - 6, 3)
*(newResult + 25 - 8) = ','
memcpy(newResult + 25 - 9 - 2, result + 19 - 9, 3)
*(newResult + 25 - 12) = ','
memcpy(newResult + 25 - 12 - 3, result + 19 - 12, 3)
*(newResult + 25 - 16) = ','
memcpy(newResult + 25 - 15 - 4, result + 19 - 15, 3)
*(newResult + 25 - 20) = ','
memcpy(newResult + 25 - 18 - 5, result + 19 - 18, 3)
*(newResult + 25 - 24) = ','
memcpy(newResult + 25 - 21 - 6, result + 19 - 21, 3)
As you can see, your very last operation copies data 2 bytes before the beginning of the buffer you allocated. This is because you assume that you will always be copying 3 characters. Of course, that's not always the case.
Frankly, I don't think your version of FormatNumber should be fixed. all that pointer arithmetic and calculations are bugs waiting to happen. Here's the version I wrote, which you can use if you want. I consider it much more sane, but your mileage may vary:
const char *StatThread::FormatNumber(UINT64 number) const
{
// The longest 64-bit unsigned integer 0xFFFFFFFF is equal
// to 18,446,744,073,709,551,615. That's 26 characters
// so our buffer will be big enough to hold two of those
// although, technically, we only need 6 extra characters
// at most.
const int buflen = 64;
char *result = new char[buflen];
int cnt = -1, idx = buflen;
do
{
cnt++;
if((cnt != 0) && ((cnt % 3) == 0))
result[--idx] = ',';
result[--idx] = '0' + (number % 10);
number = number / 10;
} while(number != 0);
cnt = 0;
while(idx != buflen)
result[cnt++] = result[idx++];
result[cnt] = 0;
return result;
}
P.S.: The "off by a factor of 10" thing is left as an exerise to the reader.

At the line
DWORD nDigits = ceil(log10((double)number));
you need three digits for 100 but log 100 = 2. This means that you allocating one too few characters for char* newResult = new char[nComma+nDigits+1];. This means that the end of your heap cell is being overwritten which is resulting in the heap corruption you are seeing. Debug heap allocation may be more forgiving which is why the crash is only in debug mode.

Heap corruption is usually caused by overwriting the heap data structures. There is a lot of use of "result" and "newResult" without good boundary checking. When you do a debug build, the whole alignment changes and by chance the error doesnt happen.
I would start by adding checks like this:
DWORD nDigits = ceil(log10((double)number));
if(nDigits>=100){printf("error\n");exit(1);}
result[nDigits] = '\0';

Two things in your StatThread::PrintStat function.
This is a memory leak if the loop body executes more than once. You would reassign these pointers without calling delete[] for the previous values.
while((BytesInserted<=fileSize.QuadPart)&&flag){
...
CUnique = FormatNumber(nUnique);
CInserted = FormatNumber(nInserted);
...
}
Is this supposed to be an assignment = or a comparison ==?
if(BytesInserted=fileSize.QuadPart)
flag=false;
Edit to add:
In your StatThread::FormatNumber function this statement adds a null terminator to the end of the block but the previous chars may contain garbage (new doesn't zero allocated memory). The subsequest calls to strlen() may return an unexpected length.
newResult[nComma+nDigits]='\0';

Related

Why performance is reduced much when I run a for loop with a count of 5368709120 and few lines of memcpy?

I am allocating three large sized byte arrays and initialized them to some values. I have to perform operations on every 64 bits between these three arrays. I have created a for loop to loop through these arrays and convert consecutive 8 byte(64bit) into 64 bit integer using memcpy and perform operations between them. Later, have calculated the time taken by for loop. I have given my code here.
#include <stdio.h>
#include<iostream>
#include<ctime>
#include<Windows.h>
#include<chrono>
using namespace std;
BYTE* buffer1;
BYTE* buffer2;
BYTE* buffer3;
int main()
{
unsigned long long offsetValue = 0;
int64_t data1, data2, data3;
unsigned long long BufferSize = 5368709120;
buffer1 = (BYTE*)malloc(BufferSize);
buffer2 = (BYTE*)malloc(BufferSize);
buffer3 = (BYTE*)malloc(BufferSize);
memset(buffer1, 0, BufferSize);
memset(buffer2, 1, BufferSize);
memset(buffer3, 1, BufferSize);
bool overallResult = false;
bool stopOnFail = false;
auto start = chrono::steady_clock::now();
for (unsigned long long i = 0, cycle = 0; i<BufferSize; i += 8, ++cycle)
{
long long offset = (offsetValue * 8) + i;
if (offset> BufferSize - 1)
break;
else if (offset< 0)
continue;
memcpy(&data1, buffer1 + offset, sizeof(int64_t));
if (data1 == -1)
continue;
memcpy(&data2, buffer2 + offset, sizeof(int64_t));
memcpy(&data3, buffer3 + offset, sizeof(int64_t));
int64_t Exor = data2 ^ data3^-1;
int64_t Or = Exor | data1;
bool result = Or == -1;
overallResult &= result;
if (!result)
{
if (stopOnFail)
break;
}
}
auto ending = chrono::steady_clock::now();
cout << "For loop Execution time in milliseconds :"
<< chrono::duration_cast<chrono::milliseconds>(ending - start).count()
<< " ms" << endl;
free(buffer1);
free(buffer2);
free(buffer3);
system("pause");
return 0;
}
For loop count of 4294967296 gave me a time of 760 milliseconds. But for loop count of 5368709120 gives me a time of 25000 milliseconds. What is draining the time in for loop? How should I optimize?
1. You're not using the value overallResult outside the loop, so a good optimizing compiler can optimize away the loop entirely. MSVC is probably isn't that smart, but it's still a good idea to e.g. print out overallResult at the end.
2. You're allocating (and actually using) 3 × 5,368,709,120 bytes = 15 GB. A Windows 10 system uses a lot more than 1 GB to run (especially in combination with Visual Studio), so on a system with 16 GB, allocating 15 GB would inevitably cause paging, which is most probably what you're observing (also, a ~20..40x slowdown is characteristic of memory paging).
To verify:
Open up Performance Monitor (perfmon.exe)
Add Counters -> Paging File -> % Usage
Run your program
If the paging counters are > 0, then you don't have enough RAM, and looping over memory will slow down due to reading of pages from disk.
You can also watch RAM usage in Task Manager -> Performance tab.

Get file extension native method

I'm using MVS 2010, C++ program without using CRT.
Implementation of finding extension of file:
LPWSTR findExtension(LPCWSTR fileName)
{
int pos = findchr(fileName, L".");
if (pos != -1) {
int lenght = lstrlenW(fileName);
wchar_t* extension = (wchar_t*)HeapAlloc(GetProcessHeap(), NULL, lenght - pos + 1);
for (int i = 0; i < lenght - pos; i++)
{
extension[i] = fileName[pos + 1 + i];
}
extension[lenght - pos] = 0;
LPWSTR ret = extension;
return ret;
}
}
There are problems. Sometimes it can crash application. And memory leak.
How to fix this issues?
Your problem is:
int lenght = lstrlenW(fileName);
lenght is the number of wide characters not the number of bytes. So you allocate a too small buffer here:
wchar_t* extension = (wchar_t*)HeapAlloc(GetProcessHeap(), NULL, lenght - pos + 1);
You need to use this instead:
wchar_t* extension = (wchar_t*)HeapAlloc(GetProcessHeap(), NULL, sizeof(wchar_t) * (lenght - pos + 1));
HeapAlloc() function will allocate memory on heap. When you're not using the heap memory block you need to free it. You can use:
BOOL HeapFree( HANDLE hHeap,DWORD dwFlags,_Frees_ptr_opt_ LPVOID lpMem);
Even though you're in a {....} module, heap will not behave just like the stack that it will automatically FREE its memory. The more you reuse the function the more it will allocate memory to the heap and your private memory size(see task manager) will grow bigger and bigger. And by the time the OS can't give you memory it will suddenly crash.
Not freeing heap memory after using is bad if your program is running a long period (worst case if infinite time) and always perform processes.

Heap corruption while trying to free a wchar_t pointer

This is a code that evaluates if a wide string is either L"false" or L"true", but when I try to run it, it gives me this error when trying to free the duplicate string pointer "HEAP CORRUPTION DETECTED: after Normal block(#135756) at 0x00000000002EB3A0. CRT detected that the application wrote to memory after end of heap buffer.".
Here is the inline code:
const wchar_t* sequence = L"false";
wchar_t* duplicate;
size_t length = wcslen(sequence) + 1;
duplicate = static_cast<wchar_t*>(malloc(length));
wcscpy_s(duplicate, length, sequence);
int boolean = -1;
if (wcscmp(duplicate, L"false") == 0) {
boolean = 0;
}
else if (wcscmp(duplicate, L"true") == 0) {
boolean = 1;
}
free(duplicate);
All the string pointers seem to be OK right before the free statement. I am sure I have done some serious mistake simply because I was able to corrupt the heap.
Compiler: Microsoft Visual Studio 2015 RC
Processor: Inter Core i5-3450 3.10 GHz
Use
duplicate = static_cast(malloc(length * sizeof(wchar_t));
otherwise you do not hane enough space for the wide string

buserror given by quickfix

I was trying to get a simple demo quickfix program to run on solaris, namely http://www.codeproject.com/Articles/429147/The-FIX-client-and-server-implementation-using-Qui prior to getting it to do what I want it to.
unfortunately in main the application gives a bus error when
FIX::SocketInitiator initiator( application, storeFactory, settings, logFactory);
is called
examine the core dump with gdb and I see
(gdb) where
#0 FIX::SessionFactory::create (this=0xffbfee90, sessionID=#0x101fe8, settings=#0x100e34)
at FieldConvertors.h:113
#1 0xff2594ac in FIX::Initiator::initialize (this=0xffbff108) at stl_tree.h:246
#2 0xff25b270 in Initiator (this=0xffbff108, application=#0xffbff424,
messageStoreFactory=#0xffbff1c4, settings=#0xffbff420, logFactory=#0xffbff338)
at Initiator.cpp:61
#3 0xff25f8a8 in SocketInitiator (this=0xffbff108, application=#0xffbff3c8,
factory=#0xffbff388, settings=#0xffbff408, logFactory=#0xffbff338) at SocketInitiator.cpp:52
#4 0x0004a900 in main (argc=2, argv=0xffbff4c4) at BondsProClient.cpp:42
So I look in FieldConverters.h and we have the code
inline char* integer_to_string( char* buf, const size_t len, signed_int t )
{
const bool isNegative = t < 0;
char* p = buf + len;
*--p = '\0';
unsigned_int number = UNSIGNED_VALUE_OF( t );
while( number > 99 )
{
unsigned_int pos = number % 100;
number /= 100;
p -= 2;
*(short*)(p) = *(short*)(digit_pairs + 2 * pos);
}
if( number > 9 )
{
p -= 2;
*(short*)(p) = *(short*)(digit_pairs + 2 * number); //LINE 113 bus error line
}
else
{
*--p = '0' + char(number);
}
if( isNegative )
*--p = '-';
return p;
}
Looking at this I'm actually not surprised this crashes. It's de-referencing a char* pointer passed to the function as a short, without checking the alignment, which can't be known. This is illegal to any C / C++ standard and since the sparc processor can't perform an unaligned memory access, the thing obviously crashes. Am I being really thick here, or is this a stone cold bug of massive proportions in the quickfix headers? quickfix IS (according to their website) supposed to compile and be usable on solaris sparc. Does anyone know of any work around for this? The option of edit thew header to sprintf springs to mind, as does aligning some things. Or is the a red herring with something different causing an unaligned buffer?
If it's crashing due to misaligned loads/stores then you could replace lines such as:
*(short*)(p) = *(short*)(digit_pairs + 2 * number);
with a safer equivalent using memcpy:
memcpy((void *)p, (const void *)(digit_pairs + 2 * number), sizeof(short));

Double free or memory corruption

I have a code like this
char *verboseBuf = NULL;
if(somethin){
for(a loop){
for(another loop){
if(somethin else){
if(curl execution){
if(fail){
verboseBuf = (char *) malloc(sizeof(char) * (currSize +1));
fread(verboseBuf, 1, currSize, verboseFd);
verboseBuf[currSize + 1] = '\0';
string verbose = verboseBuf;
free(verboseBuf);
}
}
}
}
}
}
The only place that i use the verboseBuf is inside the final if loop. but i get
*** glibc detected *** ./test: double free or corruption (!prev): 0x13c13290 ***
But how can be freeing it twice if i only use it in one place? and everytime i use it, i free it.
I tried using addr2line to find the place where it was freed previously but all got was a ??:0.
This line is writing one byte past the end of your buffer.
verboseBuf[currSize + 1] = '\0';
That message doesn't specifically mean that you freed something twice, it means that glibc detected heap corruption, and freeing things twice is one common cause of that, but not the only one.
In this case, the line
verboseBuf[currSize + 1] = '\0';
is overflowing the end of your buffer, corrupting whatever bookkeeping data the allocator stored after it. Remove the +1 and it should work.
Make verboseBuf[currSize + 1] = '\0'; as verboseBuf[currSize] = '\0';