Help with a tricky bug


#1

Hi all, I normally don't post bugs up here, as I invariably find the problem straight after, and it's always due to my own foolishness. But I'm at my wits' end. I have a bug that only manifests in Release builds, so I can't debug it as usual. 

The crash happens irregularly, so I suspect it's a memory error, but I can't see where it's being caused. It always sends me to the same place in the stack trace, a piece of audio code (an oscillator). It stops at an assembly instruction movss. On looking this up, it appears to be an SSE instruction, but I haven't written any SIMD in this function nor used any AudioSampleBuffer methods that use SSE. Does this mean the compiler is vectorizing my code for me?

Does anyone have tips for debugging this kind of thing, or debugging audio code in general, which is such a PITA? Many thanks.


#2

The first thing to check for with Release bugs (not happening in Debug) are uninitialized variables.

Rail


#3

Thanks for the suggestion. I have a warning enabled for that, because it's bitten me so many times in the past! To be honest I think this is  something to do with a pool of memory I'm using to share buffers between objects. I'm still not 100% sure what's going wrong, but I feel like I'm on the wrong track. If nothing else, this bug has given me the prod I needed to start learning some assembly language.


#4

It seems that you should rather focus on avoiding undefined behaviour in your code (uninitialised variables, dangling pointers, etc.)

Being able to read assembler is great, but usually in those cases the actual problem doesn't lie in the part of the code that crashes, but elsewhere, so being able to read the assembly is not always helpful in fixing the actual bug.


#5

Also watch out for operations done inside jasserts: in Release builds, they are simply not compiled thus they may leave you in an indetermined state.

For example: (it's stupid, just to illustrate the concept)

uint8* buffer;

// the purpose of the jassert below is to catch errors in the creation of the buffer,
// but choosing to call createBuffer() inside it is unfortunate, because in Relase that won't happen

jassert (buffer = createBuffer());  

// at this point buffer is correctly created in Debug, but is an uninitialized pointer in release