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++!
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)
Friday, 18 October 2013
Tuesday, 17 September 2013
MS Compiler Bloat and broken MSBuild 4.0
Windows XP goes out of support next year so my work is finally upgrading to windows 7. This has provided the impetus to port our VS6.0 project to VS2010 as VS6.0 will not install on Windows 7.
The port was fairly uneventful, just a few minor fixes because C++ wasn't standardized back in 98 when VS6.0 was released, so the code would not compile without a few tweaks.
The project is fairly large and takes 30 mins to build via Atlassian Bamboo build server. Imagine my dismay when I found the VS2010 version of the project took 90 mins!!! 15 years of compiler progress and they have managed to slow it down to one third of the speed!
So, I thought.... MSBuild has support for parallel builds - lets give that a crack! Unfortunately, it failed to build. After wasting a day I found this.
Apparently MSBuild 4.0 has a bug where it doesn't respect the project dependencies, so it gets the build order wrong.
Anyway, if you are using Bamboo with VS2010, use the DEVENV.EXE task for building projects, not MSBuild - it's broken!
The project is fairly large and takes 30 mins to build via Atlassian Bamboo build server. Imagine my dismay when I found the VS2010 version of the project took 90 mins!!! 15 years of compiler progress and they have managed to slow it down to one third of the speed!
So, I thought.... MSBuild has support for parallel builds - lets give that a crack! Unfortunately, it failed to build. After wasting a day I found this.
Apparently MSBuild 4.0 has a bug where it doesn't respect the project dependencies, so it gets the build order wrong.
Anyway, if you are using Bamboo with VS2010, use the DEVENV.EXE task for building projects, not MSBuild - it's broken!
Tuesday, 27 August 2013
bye bye vodafail
This month I inadvertently went over my data quota on my Vodafone service and copped a bill for $210. The culprit was my 3 yo son watching Thomas videos on YouTube.
I bought a data booster pack -2Gb for $30 dollars - that's $15 per gig, but it was too late, they had already charged me at a rate of $250 per Gb!
Since I am no longer under contract I'm free to leave for a player like Boost, which is offering unlimited calls and SMS with 3Gb of data - which is twice the data allowance of my Vodafone plan for only $5 per month more, and no chance of running up an excess data bill. I called customer support, thinking they would try their best to keep a happy customer, since they have been bleeding customers since the vodafail network debacle , but no... all they did was try to upsell me on plans. I even told them I was thinking of porting out...
Anyway, the port from Vodafone to Boost took less than an hour. Bye bye vodafail!
Friday, 9 August 2013
raspberry pi prototyping kit from adafruit arrived today
I already have a project in mind - an internet connected security door buzzer so I can open the front door to my apartment block with my iphone. Stay tuned for construction details
Saturday, 23 February 2013
Making Music on an iPad
Here's a little childrens song I wrote and recorded on my iPad using GarageBand - really lo-fi, just using the internal microphone and the virtual instruments available in GarageBand for iPad. I did the final mixdown on my macbook.
It's a song about breakfast!
Monday, 31 December 2012
Upgrading the RAM in a 2006 MacBook Pro (Merom) - MacBookPro2,2
I just upgraded the RAM in a 2006 Macbook Pro with the Merom Chipset - the system identifier for this mac is MacBookPro2,2 ( About this Mac ->More Info->System Report).
The ram it comes with is DDR2 667 Mhz 5300 SO-DIMM - this ram is hard to come by these days and I heard conflicting reports about whether higher speed RAM would work. Apparently the later model Penryn chipsets machines would not downclock the RAM and fail to to boot.
Anyway, my local computer store had some Patriot 800Mhz RAM for much cheaper than the Mac spec RAM could be had on ebay, so I took a chance and bought some.
After a false start because I didn't seat the RAM properly, I can report that 800 Mhz RAM works on my MacBookPro2,2 just fine!
The ram it comes with is DDR2 667 Mhz 5300 SO-DIMM - this ram is hard to come by these days and I heard conflicting reports about whether higher speed RAM would work. Apparently the later model Penryn chipsets machines would not downclock the RAM and fail to to boot.
Anyway, my local computer store had some Patriot 800Mhz RAM for much cheaper than the Mac spec RAM could be had on ebay, so I took a chance and bought some.
After a false start because I didn't seat the RAM properly, I can report that 800 Mhz RAM works on my MacBookPro2,2 just fine!
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)
