Dangerous error Visual c++ 2005 - c++

I bumped into a very serious error using visual studio 2005, running a C++ Win32 Console application. The problem will show when running the code below (simplified), using the following project properties: C++|optimization|optimization|/O2 (or /O1, or /Ox), C++|optimization|Whole program optimization|/GL, linker|optimization|/ltcg
#include "stdafx.h"
#include <iostream>
using namespace std;
const int MAXVAL=10;
class MyClass
{
private:
int p;
bool isGood;
public:
int SetUp(int val);
};
int MyClass::SetUp(int val)
{
isGood = true;
if (MAXVAL<val)
{
int wait;
cerr<<"ERROR, "<<MAXVAL<<"<"<<val<<endl;
cin>>wait;
//exit(1); //for x64 uncomment, for win32 leave commented
}
if (isGood) p=4;
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int wait=0, setupVal1=10, setupVal2=12;
MyClass classInstance1;
MyClass classInstance2;
if (MAXVAL>=setupVal1) classInstance1.SetUp(setupVal1);
if (MAXVAL>setupVal2) classInstance2.SetUp(setupVal2);
cerr<<"exit, enter value to terminate\n";
cin>>wait;
return 0;
}
The output shows that value 10 is smaller then value 10! I already found out that changing setting /O2 to /Od solves the problem (setting /Og, which is part of /O2, causes the problem), but that really slows down the execution time. Also changing the code a bit can solve it but hey, I can never be sure that the code is reliable. I am using Visual studio 2005 professional (Version 8.0.50727.867), os windows 7.
My questions are: can someone try to reproduce this error using Visual Studio 2005, (I already tried VS 2010, no problem), and if so, what happens here?
Can I assume that newer versions have solved this problem (I consider buying VS 2012)
Thank you

You can reduce your example significantly and still get the same problem! You don't need two instances, and you don't need any of the other local or member variables. Also, you can hardcode MAXVAL.
Quick summary of what "solves" the problem:
making MAXVAL a nonconst int
setting setupVal2 to a value less than 10
surprisingly, changing the condition 10<val to val>10 !!!
Here's my minimal version to reproduce the problem:
#include "stdafx.h"
#include <iostream>
using namespace std;
class MyClass
{
public:
int SetUp(int val);
};
int MyClass::SetUp(int val)
{
if (10<val)
cout<<10<<"<"<<val<<endl;
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int setupVal1=10, setupVal2=12;
MyClass classInstance;
classInstance.SetUp(setupVal1);
classInstance.SetUp(setupVal2);
cin.get();
return 0;
}
The problem, as witnessed by the disassembly, is that the compiler thinks 10<val is always true and therefore omits the check.
_TEXT SEGMENT
?SetUp#MyClass##QAEHH#Z PROC ; MyClass::SetUp
; _val$ = ecx
; 16 : if (10<val)
; 17 : cout<<10<<"<"<<val<<endl;
mov eax, DWORD PTR __imp_?endl#std##YAAAV?$basic_ostream#DU?$char_traits#D#std###1#AAV21##Z
push eax
push ecx
mov ecx, DWORD PTR __imp_?cout#std##3V?$basic_ostream#DU?$char_traits#D#std###1#A
push 10 ; 0000000aH
call DWORD PTR __imp_??6?$basic_ostream#DU?$char_traits#D#std###std##QAEAAV01#H#Z
push eax
call ??$?6U?$char_traits#D#std###std##YAAAV?$basic_ostream#DU?$char_traits#D#std###0#AAV10#PBD#Z ; std::operator<<<std::char_traits<char> >
add esp, 4
mov ecx, eax
call DWORD PTR __imp_??6?$basic_ostream#DU?$char_traits#D#std###std##QAEAAV01#H#Z
mov ecx, eax
call DWORD PTR __imp_??6?$basic_ostream#DU?$char_traits#D#std###std##QAEAAV01#P6AAAV01#AAV01##Z#Z
; 18 : return 1;
mov eax, 1
; 19 : }

Related

Detect debugger in c++ with zero division exception

I found function written in c++ which is able to detect debugger when I execute
xor eax, eax
div eax
but the problem is when a debugger is attached the process crashes after reaching div eax. I put that inline asm to __try and __except section but after reaching instruction div eax process just freezes. Whole code:
#include "windows.h"
#include <iostream>
using namespace std;
LONG WINAPI UnhandledExcepFilter(PEXCEPTION_POINTERS pExcepPointers) {
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)pExcepPointers->ContextRecord->Eax);
pExcepPointers->ContextRecord->Eip += 2;
return EXCEPTION_CONTINUE_EXECUTION;
}
int main() {
SetUnhandledExceptionFilter(UnhandledExcepFilter);
__try {
__asm {
xor eax, eax
div eax
}
}
__except (EXCEPTION_INT_DIVIDE_BY_ZERO) {
cout << "DEBUGGER NOT FOUND" << endl;
}
return NULL;
}
I need just silently detect debugger.
Thx for any help.
Given that you are using "windows.h", you can simplify it to IsDebuggerPresent, and / or DebugBreak

Visual studio doesn't use EBP when referring to stack variable

I have the following C++ code
int myFuncSum( int a, int b)
{
int c;
c = a + b;
return c;
}
int main(int argc, char *argv[])
{
int result;
result = myFuncSum(100, 200);
return 0;
}
When I step through this in the disassembly window of Visual Studio 2008 on my Win7 Pro machine, I see the following for the call to myFuncSum():
int myFuncSum( int a, int b)
{
001C1000 push ebp
001C1001 mov ebp,esp
001C1003 push ecx
int c;
c = a + b;
001C1004 mov eax,dword ptr [a] <--------------------
001C1007 add eax,dword ptr [b] <--------------------
001C100A mov dword ptr [c],eax <--------------------
return c;
001C100D mov eax,dword ptr [c] <--------------------
}
As I have indicated, the four lines that refer to the variables a, b and c refer to them as such, not as offsets relative to EBP.
Can anyone please suggest what I need to do to Visual Studio to get it to refer to them via EBP? I have already disabled C++ optimisations in the project settings; without doing so I don't even get my function called.
The disassembler is just trying to be helpful, not spamming you too much about irrelevant details. Not entirely accidental, this syntax abbreviation is also permitted in inline assembly with the __asm keyword.
You can switch back-and-forth, right-click the disassembly window and untick Show Symbol Names. Now you'll see the real machine code:
c = a + b;
003613DE mov eax,dword ptr [ebp+8]
003613E1 add eax,dword ptr [ebp+0Ch]
003613E4 mov dword ptr [ebp-8],eax
return c;
003613E7 mov eax,dword ptr [ebp-8]

Is it now wrong to "return" from a "switch" statement in C++11? [duplicate]

This question already has answers here:
Possible compiler bug in Visual C++ 2012 (x86)?
(2 answers)
Closed 10 years ago.
Using VS2012, I noticed that a switch that's been working for several years now seems to be broken in Release builds but works correctly (or at least as it used to) in Debug builds. I can't see anything at all wrong with the code so would appreciate some feedback on the correctness of using return statements from within a switch block.
The following code compiles ok but gives the wrong output in a Release build on Win7 32-bit...
#include <stdio.h>
#include <tchar.h>
class CSomeClass
{
public:
float GetFloat(int nInt)
{
printf("GetFloat() - entered\n");
switch (nInt)
{
case 1 :
printf("GetFloat() - case 1 entered\n");
return 0.5F;
case 0 :
printf("GetFloat() - case 0 entered\n");
return 1.0F;
case 2 :
printf("GetFloat() - case 2 entered\n");
return 2.0F;
case 3 :
printf("GetFloat() - case 3 entered\n");
return 3.0F;
case 4 :
printf("GetFloat() - case 4 entered\n");
return 4.0F;
}
printf("GetFloat() - exit\n");
return 1.0F;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CSomeClass pClass;
float fValue = pClass.GetFloat(3);
printf("fValue = %f\n", fValue);
return 0;
}
If you can repeat the problem, and have a MS Connect login, maybe you can vote it up here too?
Actual results
Release build gives the following incorrect result:
GetFloat() - entered
GetFloat() - case 3 entered
fValue = 0.000000
Expected results
Debug build gives the following correct result:
GetFloat() - entered
GetFloat() - case 3 entered
fValue = 3.000000
MS Connect bug report
It sounds like it might be this bug? Where there is a problem in returning floating point values generated in a similar way?
Definitely a compiler error. Here is the stripped down asm code being executed (jumps etc. removed). The compiler removes some code it assumes to be unnecessary - even though it is not.
Release build:
// inside GetFloat
00E0104D fld dword ptr ds:[0E021D8h] // load constant float onto FPU stack
00E01068 add esp,4
00E0106B ret
// back in main
00E01098 cvtss2sd xmm0,xmm0 // convert float to double. assumes the returned value to be in xmm0
00E0109C sub esp,8
00E0109F movsd mmword ptr [esp],xmm0 // push double being printed (xmm0 is with high likelyhood = 0)
00E010A4 push 0E021B8h // push output string
00E010A9 call dword ptr ds:[0E02090h] // call printf
Debug build:
003314B0 fld dword ptr ds:[335964h] // load const float onto FPU stack
[...]
00331500 mov esp,ebp
00331502 pop ebp
00331503 ret 4
// back in main
00331598 fstp dword ptr [fValue] // copies topmost element of the FPU stack to [fValue]
0033159B cvtss2sd xmm0,dword ptr [fValue] // correctly takes returned value (now inside [fValue] for conversion to double
003315A0 mov esi,esp
003315A2 sub esp,8
003315A5 movsd mmword ptr [esp],xmm0 // push double being printed
003315AA push 335940h // push output string
003315AF call dword ptr ds:[3392C8h] // call printf
Gathering data from all the results, it's most probably compiler bug.
x64 works correctly
/O1 works correctly
well, Debug works correctly
it gives the same kind of error on both cout and printf
And, probably the most important - it's 100% standards compliant. So it should work.

Using ASM in C++

I am using the following code:
int _tmain(int argc, _TCHAR* argv[])
{
__asm{
"MOV EAX, DMSN[0]";
"LEA EBX, DMSN[0]";
"CALL EBX";
};
return 0;
}
MOV EAX and LEA EBX, will later contain two different arrays.
But as for the example they will contain the same.
I am using the following:
const BYTE DMSN[694]={blah, blah, blah};
But i am turning up with these erros:
1>c:\users\1337\documents\visual studio 2010\projects\test2\test2\test2.cpp(49): error C2400: inline assembler syntax error in 'opcode'; found 'bad token'
1>c:\users\1337\documents\visual studio 2010\projects\test2\test2\test2.cpp(50): error C2400: inline assembler syntax error in 'opcode'; found 'bad token'
1>c:\users\1337\documents\visual studio 2010\projects\test2\test2\test2.cpp(51): error C2400: inline assembler syntax error in 'opcode'; found 'bad token'**strong text**
What is wrong?
Your syntax is faulty, use it like this:-
int _tmain(int argc, _TCHAR* argv[])
{
_asm{
mov eax, DMSN[0]
lea ebx, DMSN[0]
call ebx
}
return 0;
}
for VS based compiler.
if dmsn is array, you dont have to put [0] to access first element
int _tmain(int argc, _TCHAR* argv[])
{
__asm{
mov eax, DMSN
lea ebx, DMSN
call ebx
};
return 0;
}
mov instruction will automatically check for the operand sizes and will take first 32 bits into register(eax) and 32 bit effective address to register(ebx)
VC++ 2010 express

Extremely bizarre code generation in Visual C++, for nearly identical code; 3x speed difference

The code below (reduced from my larger code, after my astonishment at how its speed paled in comparison with that of std::vector) has two peculiar features:
It runs more than three times faster when I make a very tiny modification to the source code (always compiling it with /O2 with Visual C++ 2010).
Note: To make this a little more fun, I put a hint for the modification at the end, so you can spend some time figuring out the change yourself. The original code was ~500 lines, so it took me a heck of a lot longer to pin it down, since the fix looks pretty irrelevant to the performance.
It runs about 20% faster with /MTd than with /MT, even though the output loop looks the same!!!
The difference in the assembly code for the tiny-modification case is:
Loop without the modification (~300 ms):
00403383 mov esi,dword ptr [esp+10h]
00403387 mov edx,dword ptr [esp+0Ch]
0040338B mov dword ptr [edx+esi*4],eax
0040338E add dword ptr [esp+10h],ecx
00403392 add eax,ecx
00403394 cmp eax,4000000h
00403399 jl main+43h (403383h)
Loop with /MTd (looks identical! but ~270 ms):
00407D73 mov esi,dword ptr [esp+10h]
00407D77 mov edx,dword ptr [esp+0Ch]
00407D7B mov dword ptr [edx+esi*4],eax
00407D7E add dword ptr [esp+10h],ecx
00407D82 add eax,ecx
00407D84 cmp eax,4000000h
00407D89 jl main+43h (407D73h)
Loop with the modification (~100 ms!!):
00403361 mov dword ptr [esi+eax*4],eax
00403364 inc eax
00403365 cmp eax,4000000h
0040336A jl main+21h (403361h)
Now my question is, why should the changes above have the effects they do? It's completely bizarre!
Especially the first one -- it shouldn't affect anything at all (once you see the difference in the code), and yet it lowers the speed dramatically.
Is there an explanation for this?
#include <cstdio>
#include <ctime>
#include <algorithm>
#include <memory>
template<class T, class Allocator = std::allocator<T> >
struct vector : Allocator
{
T *p;
size_t n;
struct scoped
{
T *p_;
size_t n_;
Allocator &a_;
~scoped() { if (p_) { a_.deallocate(p_, n_); } }
scoped(Allocator &a, size_t n) : a_(a), n_(n), p_(a.allocate(n, 0)) { }
void swap(T *&p, size_t &n)
{
std::swap(p_, p);
std::swap(n_, n);
}
};
vector(size_t n) : n(0), p(0) { scoped(*this, n).swap(p, n); }
void push_back(T const &value) { p[n++] = value; }
};
int main()
{
int const COUNT = 1 << 26;
vector<int> vect(COUNT);
clock_t start = clock();
for (int i = 0; i < COUNT; i++) { vect.push_back(i); }
printf("time: %d\n", (clock() - start) * 1000 / CLOCKS_PER_SEC);
}
Hint (hover your mouse below):
It has to do with the allocator.
Answer:
Change Allocator &a_ to Allocator a_.
For what it's worth, my speculation for the difference between /MT and /MTd is that the /MTd heap allocation will paint the heap memory for debugging purposes making it more likely to be paged in - that occurs before you start the clock.
If you 'pre-heat' the vector allocation, you get the same numbers for /MT and /MTd:
vector<int> vect(COUNT);
// make sure vect's memory is warmed up
for (int i = 0; i < COUNT; i++) { vect.push_back(i); }
vect.n = 0; // clear the vector
clock_t start = clock();
for (int i = 0; i < COUNT; i++) { vect.push_back(i); }
printf("time: %d\n", (clock() - start) * 1000 / CLOCKS_PER_SEC);
It's strange that Allocator& will break the alias chain while Allocator will not.
You can try
for(int i=vect.n; i<COUNT;++i){
...
}
to enforce i and n are synchronized.
This will make vc much easier to optimize.
emm... It seems that the "fastest" code
00403361 mov dword ptr [esi+eax*4],eax
00403364 inc eax
00403365 cmp eax,4000000h
0040336A jl main+21h (403361h)
is somewhat over-optimized. In this loop, vect.n is ignored at all...
If there was an exception happened in the loop, vect.n will not be updated correctly.
So the answer might be: when you use Allocator, vc figures out that vect.n will be never used again,
so that it can be ignored. It's amazing, but in general it's not so useful and dangerous.