Deallocation crash

Hi, I’m having issues with a prototype module that is crashing upon attempting to remove it.

The sourcecode can be found here: Create beta.cpp by Geekachuqt · Pull Request #2 · Geekachuqt/3HR · GitHub

Basically, the crash occurs if the module has ever left the “IDLE” switch case. If I add the module, and then immediately remove it without letting it interact with the rest of the cases, it works fine.

The crash points to a mingw64 file called “new_allocator.h”, and references the following section:

      // __p is not permitted to be a null pointer.
      void
      deallocate(_Tp* __p, size_type __t __attribute__ ((__unused__)))
      {

So it seems to me like I’m somehow causing a deconstruct to be called on a null pointer. However, I can’t figure out what I could possibly have done to cause this.

If I keep stepping forward when hitting the new_allocator.h file, I eventually end up back in my module code, where it points to ModuleWidget object, but that seems unlikely to be the real cause of this?

The problematic code likely exists somewhere in the switch case, but it all looks solid to me, and as the debugger isn’t pointing me to my own code, it’s difficult to debug.

Could anyone have a look and see if they can spot something that looks off?

I don’t see anything there that’s obvious to me. A few comments:

  • Have you run this under address sanitizer? It usually finds problems like this very quickly.
  • It seems you have run this in gdb. If it runs to the crash can you use bt to see what is the deallocation that is crashing?
  • It’s a little unconventional to allocate memory in the the process call like you do (indirectly via std::vector::resize). But it should not crash. it is, however allocating and deallocating on different threads.
  • are you sure that you are not going past the bounds of playBuffer, possibly with a negative playHead? Admittedly that should just throw an exception. Can you use the debugger to break on a thrown exception? (yes, I see that is possible).
  • As an experiment replace the vector with a static array float playBuffer[SOME_HUGE_NUMBER].
  • I don’t think your code would respond correctly to the user changing the sample rate while this module is running.

They are:

if(RecordingState != IDLE && BufferCounter <= PlayBuffer.size()){
   PlayBuffer[BufferCounter] = ...

Note the <= there.

@3HR: Crashes on deallocation are often caused by memory corruption, including writing off the end of an array. (Just because the comment on deallocate talks about null pointers, that doesn’t mean that’s the only way it can fail.)

ah, right you are. Also, why is buffer counter a float? shouldn’t it be a size_t? or some integral type?

Oh, and I was wrong about the exception: " Returns a reference to the element at specified location pos . No bounds checking is performed." I was thinking of std::vector::at, which does have bounds checking.

Ha, I hadn’t seen that. Now I want a vector type that accepts a float as the index and returns interpolated results. :slight_smile:

> v = [1, 2, 3]
> v[1]
2
> v[1.5]
2.5
1 Like

Haha, I’m sure you could write one. Maybe themplatized on interpolation algorithm?

1 Like

use rack::math::interpolateLinear(const float * p, float x)

Linearly interpolates an array p with index x.

The array at p must be at least length floor(x) + 2

1 Like

Didn’t we all learn the formula for a line between two points in grade school?

This was the one. Really appreciate everyones help!

2 Likes