Difference between Debug and Release Builds

 

I wrote this document way back in 2010, which I found sitting on my computer. I wrote it for folks in our QA department. But I thought it good enough to share with other folks since it describes some basic things. So here is the document:

In a debug build of max, uninitialized memory is initialized with not garbage, but a certain pattern used to help catch bugs: 0xcccccccc.

For instance:

0x0017EBD8 cccccccc
0x0017EBDC 00000000
0x0017EBE0 00000000
0x0017EBE4 00000000
0x0017EBE8 00000000
0x0017EBEC 00000302
0x0017EBF0 cccccccc
0x0017EBF4 3ed6d0e0

Uninitialized memory is marked with this pattern to help catch bugs. For any pointer dereferencing this value will cause an access violation and crash the application.

Case Study

The animation reaction manager displays a curve control. That curve control can of course display many curves. Each curve can contain many key points.

clip_image002

And here are the points:

clip_image004

The problem is manifested when you insert a point into the middle of the curve. You should expect this:

clip_image006

But instead, in a debug build you get this:

clip_image008

The problem is not the curve control, but actually the reactor controller. The reactor controller goes back and alters the points after the point was correctly inserted. (A bug was fixed by me btw) This reactor controller does its dirty business after the UI widget has already correctly displayed its data. This highlights two bugs:

1. Why is the reactor controller modifying the UI control when the UI was already correctly displayed?

2. Why is the reactor controller modifying the point with such a massive value?

The point where the first point gets altered is in the Reactor::UpdateCurves function in the following file:
…3dswinsrcmaxsdksamplescontrollersreactorreactor.cpp.

In this code:

CurvePoint pt = curve->GetPoint(0,i);
// pt here is correct
switch (type)
{
case REACTORFLOAT:
pt.p = Point2(masterState->fvalue, slaveStates[i].fstate);
break;

}
DbgAssert(pt.p.y > -1000.0); // assert fails since pt is incorrect
curve->SetPoint(0,i, &pt, FALSE, TRUE);

The value for slaveStates[i].fstate is the following floating point number:

-1.0737418e+008

Where did this value come from?

Well examining it in the debugger’s memory shows this:

memory address of some memory:

0x0017EBD8 cccccccc

As you can see, a debug build take uninitialized memory and fills it with 0xcccccccc. This is to help catch errors. Now if you take that value and interpret it as an integer you get:

0x0017EBD8 -858993460

And if you interpret it as unsigned integer you get:

0x0017EBD8 3435973836

And if you interpret those bits as a floating point number you get:

0x0017EBD8 -1.0737418e+008

That is scientific notation for -1.0737418 x 10^8, or simply -1.0737418 x 100,000,000 or rather, -107374180.0. Or basically negative 107 million.

So this explains why the value of the first point is such a massive negative number. Solving this bug is not the point of this document, but is another story altogether.

In every single Debug build (On Windows platforms), all over the world, all uninitialized variables (on windows platforms) will always be 0xcccccccc. That number is always rendered as the same floating point value shown above. It is always the same with NO EXCEPTIONS.

That means if you want predictability in reproducing bugs you go with a debug build. If you want random behavior you go with a release build:

Here is the same work-flow in a release build:

Max 2010 (Release build):

clip_image010

The inserted point has a completely random y position (thankfully not as big as -107 million!). Also the first point is assigned to a random value. What is the random value? It is whatever the value was the last time memory was used there in that memory location. That memory could be clean, or it could be leftover from anything else. It could be memory that was last used 2 seconds ago, or 2 hours ago, or 2 days ago.

So again, if you see bugs with random behavior, it’s most likely an uninitialized variable. If you want to narrow down the repro steps, and actually solve it, use a debug build.

Advertisements

Developers who litter in the code

Over the years an old code base accumulates a lot of  junk left over by programmers. Some of this is what I call vacation signs. This is a small explicit statement left in the code in the form of a comment (or a bug) stating that the developer was there. For instance:

// mjm - 06.12.00 - begin

...

// mjm - end

So now, not only do I know where his changes started, thankfully he informed the entire world where his changes ended. This is equivalent to taking a vacation to Italy and pounding a small sign in the ground when you arrived in a town stating “I <insert name here> arrived in Milan on Feb 1 2004”. And imagine when you left, you then pounded another small sign into the ground (perhaps at the other end of town?) stating your name and the date that you left. This is cute for the pictures send to your mom, but sooner or later the mayor of Milan will start to get offended at stupid tourists who do this, and will send the constables to arrest the idiot foreigner who is littering his town. This if course is utter stupidty. And in the case of these vacation signs left in our code above, they are an utter nuisance. Especially when there are thousands of these little signs.