I have just installed the recently released Microsoft Visual Studio 2013 and the most striking thing about it seems to be the sheer arrogance of Microsoft and contempt for its customers.
It needs Windows 7 or greater to install which is fair enough - even though my corporate desktop is still Windows XP (not for long as it goes out of support in April 2014).
No, the ridiculous thing is that VS 2013 requires you to install IE 10 before it can be installed. That's right - you have to upgrade your browser to IE10 before you can install the IDE!
This is a complete dealbreaker for many corporate environments.
Fortunately here's a workaround windows command script. VS2013 seems to work just fine with ie8 so it seems to be a marketing driven decision only.
@ECHO OFF
:IE10HACK
REG ADD "HKLM\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer" /v Version /t REG_SZ /d "9.10.9200.16384" /f
REG ADD "HKLM\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer" /v svcVersion /t REG_SZ /d "10.0.9200.16384" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Internet Explorer" /v Version /t REG_SZ /d "9.10.9200.16384" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Internet Explorer" /v svcVersion /t REG_SZ /d "10.0.9200.16384" /f
GOTO EXIT
:REVERTIE
REG DELETE "HKLM\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer" /v svcVersion
REG DELETE "HKLM\SOFTWARE\Microsoft\Internet Explorer" /v svcVersion
REG ADD "HKLM\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer" /v Version /t REG_SZ /d "8.0.7601.17514" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Internet Explorer" /v Version /t REG_SZ /d "8.0.7601.17514" /f
GOTO EXIT
:EXIT
The other act of corporate arrogance is that they have deprecated non-unicode MFC applications, with the lame excuse that the 64 Mb MFC MBCS libraries would bloat their 5.7 Gb distribution of VS2013. You can still build MBCS applications but the libraries need to be downloaded separately from here.
Porting a legacy app from mbcs to Unicode is a non-trivial task... especially if there is direct pointer manipulation that assumes 8 bit chars sprinkled through the code base. This would be a whole lot of pain for zero gain.
Interesting computer programming things, hardware hacks, electronics, ai, music and other stuff I find interesting
Labels
3G
(1)
8600GT
(1)
AI
(4)
amazon
(1)
API
(1)
apple
(3)
apple mail
(1)
atlassian
(1)
audio
(1)
bambo
(1)
Bamboo
(1)
bloat
(1)
boost
(1)
bugbear
(1)
C++
(5)
calling conventions
(1)
cdecl
(1)
chromecast
(1)
CI
(1)
compiler
(1)
continuous integration
(1)
coursera
(1)
custom domain
(1)
debugging
(1)
deltanine
(1)
diagnosis
(1)
diy
(5)
DLL
(1)
dns
(1)
don't be evil
(1)
ec2
(1)
education
(1)
electronics
(1)
express checkout
(1)
fail
(6)
fink
(1)
firewire
(1)
free hosting
(1)
GAE
(1)
google
(1)
Google App Engine
(4)
H170
(1)
hackerx
(1)
hackintosh
(1)
Haskell
(3)
homebrew
(2)
i1394
(1)
icloud
(2)
iOS 9
(1)
ipad2
(2)
jobhunting
(2)
lag
(1)
letsencrypt
(2)
libjpeg
(1)
linux
(1)
mac
(2)
mbcs
(1)
mechanic
(1)
memory
(1)
MFC
(3)
Microsoft
(1)
migration
(1)
ML
(1)
mobile
(1)
movi
(1)
MSBuild
(1)
music
(1)
naked domain
(1)
NLP
(2)
o2 sensor
(1)
obd
(1)
Optiplex960
(1)
osx
(1)
outlook express
(1)
payments
(1)
paypal
(1)
photos
(2)
PIL
(1)
Project Euler
(1)
projectmix
(1)
python
(2)
raspberrypi
(3)
recruitment
(1)
renwal
(1)
skylake
(1)
soundcloud
(1)
ssl
(2)
stdcall
(1)
stripe
(1)
subaru
(2)
supermemo
(1)
supermemo anki java
(1)
sync
(2)
Telstra
(1)
tests
(1)
thunderbird
(1)
udacity
(1)
unicode
(1)
Uniform Cost Search
(1)
university
(1)
upgrade
(2)
vodafail
(1)
vodafone
(1)
VS2010
(1)
vs2013
(1)
VS6.0
(1)
weather
(1)
win
(1)
Win32
(1)
Z170
(1)
Showing posts with label MFC. Show all posts
Showing posts with label MFC. Show all posts
Thursday, 24 October 2013
Friday, 18 October 2013
More than I ever wanted to know about Win32 calling conventions...
Just spent the last day trying to debug a weird bug - one of those works in Debug builds but crashes in Release builds issues in a C++ MFC application. After tweaking some compiler settings I discovered it wouldn't crash if I disabled optimizations in release mode, but rather than doing that I thought I would dig down to find the root cause.
After much setting of breakpoints and attaching the debugger I found it was crashing in a call to CString::Format() - but only subsequent to a call to a function in 3rd party DLL that was used for encryption. The origins of this DLL were long ago lost in the mists of time so unfortunately there was no documentation.
The function was called by dynamically loading the DLL and calling ::GetProcAddress() to obtain the function pointer, which had the following signature:
typedef long ( __stdcall* LPFNDLLENCRYPT)(const char *, const char *, char *);
__stdcall is used to call most of the Win32 apis. This calling convention can generate smaller code, as the called function performs the stack cleanup code.
__cdecl calling convention relies on the caller to cleanup the stack frame, and since functions are typically called from more than one place in the code, the additional stack cleanup code bloats the code.
On a hunch, I changed the function signature to:
typedef long ( __cdecl* LPFNDLLENCRYPT)(const char *, const char *, char *);
and lo and behold - it fixed the bug!
It seems the DLL was using __cdecl calling convention and expected the caller to cleanup the stack frame, but since the function pointer incorrectly declared it as __stdcall the compiler was not generating the stack cleanup code. This left the stack in a corrupted state which caused the next call to the CString::Format function in the MFC DLL to fail. Presumably the Debug build was more resilient with respect to stack corruption.
Here's a really useful article on calling conventions on CodeProject which explains calling conventions in more detail than you would ever want to know.... unless your debugging weird bugs due to calling conventions!
I love C++!
After much setting of breakpoints and attaching the debugger I found it was crashing in a call to CString::Format() - but only subsequent to a call to a function in 3rd party DLL that was used for encryption. The origins of this DLL were long ago lost in the mists of time so unfortunately there was no documentation.
The function was called by dynamically loading the DLL and calling ::GetProcAddress() to obtain the function pointer, which had the following signature:
typedef long ( __stdcall* LPFNDLLENCRYPT)(const char *, const char *, char *);
__stdcall is used to call most of the Win32 apis. This calling convention can generate smaller code, as the called function performs the stack cleanup code.
__cdecl calling convention relies on the caller to cleanup the stack frame, and since functions are typically called from more than one place in the code, the additional stack cleanup code bloats the code.
On a hunch, I changed the function signature to:
typedef long ( __cdecl* LPFNDLLENCRYPT)(const char *, const char *, char *);
and lo and behold - it fixed the bug!
It seems the DLL was using __cdecl calling convention and expected the caller to cleanup the stack frame, but since the function pointer incorrectly declared it as __stdcall the compiler was not generating the stack cleanup code. This left the stack in a corrupted state which caused the next call to the CString::Format function in the MFC DLL to fail. Presumably the Debug build was more resilient with respect to stack corruption.
Here's a really useful article on calling conventions on CodeProject which explains calling conventions in more detail than you would ever want to know.... unless your debugging weird bugs due to calling conventions!
I love C++!
Wednesday, 7 November 2012
DLL hell
I have recently found myself working on a C++ MFC application written in MSVC 6.0 . After my initial despair about not being able to port it to VS2012, due to some legal issues – it is based on a third party product, and whilst we have the source code, and the changes required to get it to compile are minor we are required to engage the third party to make ANY code changes to their source code.
Anyway, I though the least I could do was upgrade the compiler to VS6SP6. This was mostly painless, just a few small code changes.
The most interesting compiler bug that was uncovered is illustrated below:
class foo
{
public:
foo() {}
static void bar();
protected:
bool m_var;
};
void foo::bar()
{
char * message;
message = m_var ? "foo" : "bar";
printf( message );
}
public:
foo() {}
static void bar();
protected:
bool m_var;
};
void foo::bar()
{
char * message;
message = m_var ? "foo" : "bar";
printf( message );
}
Note that a static function is able to reference an instance variable of a class so the above code should not compile... in fact, in this case it only compiles when used with the ternary operator - ? as
if( m_var )
printf("foo");
else
printf("bar");
produces the compiler error. This bug was fixed in one of the service packs.
Anyway, after upgrading my machine to VS6SP6 I found that I would encounter COM registration errors with DEBUG code built on other machines without SP6... and bizarrely even code built with SP6. Code built on my machine was okay.
These errors manifested as debug asserts such as:
"File: Ctlreg.cpp Line:520"
"File: Olecli3.cpp Line:502”
"File: Olelink.cpp Line:288”
"File: Olelink.cpp Line:291”
As the code was written to link dynamically with MFC and the c runtime library – I suspected I was in DLL hell- I had the wrong versions of some obscure dll. The best way to diagnose this is with dependency walker –also known as depends.exe. This will load an executable or dll and tell you exactly what other dll files it depends on.
In this case I found:
MFC42D.DLL
MFCO42D.DLL
MFCD42D.DLL
MSVCP60D.DLL
MSVCRTD.DLL
When I replaced these DLLs with versions from machines without the problem, the problem resolved on my machine. The question was, which DLL was the culprit? I was suspicious of the MFC dlls, as the asserts were in MFC code. It turned out to be MFCO42D.dll – the version on my machine was dated 1998 version 6.0.8168.0. The SP6 version was dated 2004 and had version 6.0.9782.0.
For some reason, VS6SP6 failed to update this DLL when installed on my machine.
Anyway, the upshot is that the MFC debug DLLs are NOT binary compatible between versions of the compiler.
Anyway, the upshot is that the MFC debug DLLs are NOT binary compatible between versions of the compiler.
Plenty of people have stumbled across this problem in my google searches, so I thought I would post this for the next person! Hope it helps you
Subscribe to:
Posts (Atom)