Monday, July 03, 2006

Memory corruption in Managed C++ .NET in Release Mode

Recently we were working with some .NET Managed C++ code, that would work in debug mode but not in Release mode. What was weirder was that on most machines, it would work in Release mode. Except when it got built by the build machine. Further probing made us realize that the biggest difference between the developer machines and the build machine was it had the Professional version of Visual Studio - which meant that it had a different set of optimizations enabled. Looking closer - the optimization we were using on the compiler was /O2 : Optimize for speed. which used a couple of underlying switches (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy). If we turned of Optimization the code would run properly and turning it out would give us garbage output. Further investigation lead us to pinpoint /Og switch as the culprit. /Og uses global optimizations. Looking at the documentation, I figured the issue is most probably because we were pinning some arrays and using both the original array and the pinned pointer to access the data. I believe the problem is most probably to do with aliasing, where the optimizer gets confused when aliasing is used in code. So our solution: We could have just disabled optimizations on the project. But we wanted to have access to the speed. So we left the optimization swith /O2 in. Instead what we did was use the pragma directive "#pragma optimize" to turn off the "Og" optimization only for those methods that used pinning and aliasing. And voila - the problem is all gone and the code still runs nice and fast.

No comments: