Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.
2455 Discussions

TBB usage reports false-positive memory leaks when using crtdbg.h

Hi, we're hooking up TBB and are using it in various places, and that's all well and good. I'm trying to protect against future mem leaks and mem debugging by ensuring anything that shows up on the crtdbg radar is squashed now before some poor soul has to wade through a lot of false-positive cruft to get to a real, hard-to-track bug.

The part in question I've isolated in a unit test that uses TBB code. It reports a leak thusly:

void RunTest(...)
#ifdef _DEBUG
_CrtMemState before, after, difference;
RESULT result = _pTest->Run(_StatusMessage, _SizeofStatusMessage); // uses TBB at some point
if (_CrtMemDifference(&difference, &before, &after))
if (result != FAILURE)
result = LEAKS;
#ifdef _DEBUG
sprintf_s(_StatusMessage, _SizeofStatusMessage, "%u bytes in %u normal blocks, %u bytes in %u CRT blocks", difference.lSizes[_NORMAL_BLOCK], difference.lCounts[_NORMAL_BLOCK], difference.lSizes[_CRT_BLOCK], difference.lCounts[_CRT_BLOCK]);
return result;

To address these leaks, I first tracked and freed TBB allocated threads by doing this:
1. Create an object that handles the new/delete of task_scheduler_init.
2. In ctor, new task_scheduler_init
3. walk through all process threads and take a snap
4. run a noop parallel_for so tbb threads get created
5. walk through all process threads and take another snap
6. diff the two snaps and record the threads that have changed

On destruction of the overall object I delete the task_scheduler_init and wait on these recorded threads to shut down.

Then I created "RecycleScheduler" which destroys and recreates this object. Calling this explicitly in my unit test solved my leaks most of the time, but occasionally now I get a mem diff that has negative values as the number of bytes leaking - so it seems corrupt. This 100% happens in only the unit test that run TBB code and commenting out the one line to parallel_for always protects against any leak or corruption, so I feel I've weeded out any bugs or race conditions I have insight into.

Running through the list of tests is single-threaded, and I ensure the app comes to all but a halt between tests. There are no tasks being issued directly, currently only calls through parallel_for which I expect is completely done with all tasks by the time it returns.

Is there a rock-solid way to "reset" or turn off TBB and its memory usage at a known point for such test/mem debugging purposes and wait for its completion other than to never have instantiated it in the first place?
Please advise, thanks!
0 Kudos
0 Replies