Crash on quit

Crash on quit

Hi guys
I have tried to search the forum with no luck, so therefore im posting this thread:
I get a crash when I try to quit my application.
I get a "Unhandled exception at 0x01408936 in Test Physics.exe: 0xC0000005: Access violation reading location 0x0000002c."

pointing at line 74 at hkMemoryRouter.h: "inline Allocator& heap() { return *m_heap; }"

And here is my callstack:
> Test Physics.exe!hkMemoryRouter::heap() Line 74 + 0x26 bytes C++
Test Physics.exe!hkContainerHeapAllocator::get(const void * __formal=0x002bfbf8) Line 24 + 0x2f bytes C++
Test Physics.exe!hkArray::clearAndDeallocate() Line 330 + 0x3a bytes C++
Test Physics.exe!hkArray::~hkArray() Line 508 C++
Test Physics.exe!Main::~Main() Line 268 + 0x12 bytes C++
Test Physics.exe!WinMain(HINSTANCE__ * hInstance=0x00ff0000, HINSTANCE__ * prevInstance=0x00000000, char * cmdLine=0x00414d8f, int showCmd=0x00000001) Line 165 + 0x1c bytes C++
Test Physics.exe!__tmainCRTStartup() Line 574 + 0x35 bytes C
Test Physics.exe!WinMainCRTStartup() Line 399 C
kernel32.dll!754d1194()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!76edb495()
ntdll.dll!76edb468()

I have tried to comment out some of the parts of my destructor code, and found out that it is hkBaseSystem::quit(); that is causing the problem. Here is my destructor code:

m_pPhysicsWorld->markForWrite();
m_pPhysicsWorld->removeReference();

if (m_bVisualDebuggerActive == true)
{
m_pVisualDebugger->removeReference();
m_pPhysicsContext->removeReference();
}

delete m_pJobQueue;
m_pThreadPool->removeReference();

hkBaseSystem::quit();
hkMemoryInitUtil::quit();

I hope you can help me. Thank you

13 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

It looks like you have an hkArray of hkProcessContext*'s whose destructor is being called after you've called hkBaseSystem::quit() and hkMemoryInitUtil::quit(). The memory system has been shut down, but the array still tries to access it in order to free it's memory.

If the array is a local variable, you can just scope its use with curly braces {} to make sure that it gets cleaned up before hkBaseSystem::quit() is called. If it's a member of one of your classes (Main?), you should either make sure that the class is deleted first, or that you call hkArray::clearAndDeallocate() before calling hkBaseSystem::quit().

Hope that helps...

-Chris

Thank you for the quick reply.
But I have tried to add m_arrayPhysicsContext.clearAndDeallocate(); before hkBaseSystem::quit() but the problem is still occurring.

Do you get the exact same callstack? Can you post the declaration of your Main class?

Im trying to do the same thing but now in a console application.
But I still get the error.

Here is my callstack:
> Havok Test Console.exe!hkMemoryRouter::heap() Line 74 + 0x26 bytes C++
Havok Test Console.exe!hkContainerHeapAllocator::get(const void * __formal=0x00606268) Line 24 + 0x2f bytes C++
Havok Test Console.exe!hkArray::clearAndDeallocate() Line 330 + 0x3a bytes C++
Havok Test Console.exe!hkArray::~hkArray() Line 508 C++
Havok Test Console.exe!Physics::~Physics() Line 33 + 0x12 bytes C++
Havok Test Console.exe!Physics::`scalar deleting destructor'() + 0x2b bytes C++
Havok Test Console.exe!main() Line 7 + 0x2b bytes C++
Havok Test Console.exe!__tmainCRTStartup() Line 582 + 0x19 bytes C
Havok Test Console.exe!mainCRTStartup() Line 399 C
kernel32.dll!754d1194()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!76edb495()
ntdll.dll!76edb468()

And here is my files:

Physics.h

#ifndef PHYSICS_H
#define PHYSICS_H

// Math and base include
#include 
#include 
#include 
#include 
#include 
#include 
#include 

// Dynamics includes
#include 										
#include 	
#include 					
#include 				
#include 					

#include 			
#include 			

#include 								
#include 							
#include 	

#include 
#include 
#include 

// Visual Debugger includes
#include 
#include 				

#include 
using namespace std;

class Physics
{
public:
	Physics();
	~Physics();

	void stepSimulation(float dt);

	hkpWorld *getWorld();

private:
	void init();
	void deinit();

	hkMemoryRouter *m_memoryRouter;
	hkJobThreadPool *m_threadPool;
	int m_totalNumThreadsUsed;
	
	hkHardwareInfo m_hwInfo;
	hkCpuJobThreadPoolCinfo m_threadPoolCinfo;
	hkJobQueueCinfo m_jobQueueInfo;
	hkJobQueue *m_jobQueue;

	hkpWorld *m_physicsWorld;
	hkpWorldCinfo m_worldInfo;

	hkArray m_contextsArray;
	hkpPhysicsContext *m_context;
	hkVisualDebugger *m_vbd;
};

#endif

Physics.cpp

#include "Physics.h"

// Keycode
#include 

#if !defined HK_FEATURE_PRODUCT_PHYSICS
#error Physics is needed to build this demo. It is included in the common package for reference only.
#endif

#undef HK_FEATURE_PRODUCT_AI
#undef HK_FEATURE_PRODUCT_ANIMATION
#undef HK_FEATURE_PRODUCT_CLOTH
#undef HK_FEATURE_PRODUCT_DESTRUCTION
#undef HK_FEATURE_PRODUCT_BEHAVIOR
#define HK_EXCLUDE_LIBRARY_hkgpConvexDecomposition
#define HK_FEATURE_REFLECTION_PHYSICS
#define HK_CLASSES_FILE 
#include 

static void HK_CALL report(const char* msg, void *userArgGivenToInit)
{
	cout << msg << endl;
}

Physics::Physics()
{
	init();
}

Physics::~Physics()
{
	deinit();
}

void Physics::init()
{
	m_memoryRouter = hkMemoryInitUtil::initDefault(hkMallocAllocator::m_defaultMallocAllocator, hkMemorySystem::FrameInfo(500000));
	hkBaseSystem::init(m_memoryRouter, report);

	hkGetHardwareInfo(m_hwInfo);
	m_totalNumThreadsUsed = m_hwInfo.m_numThreads;
	m_threadPoolCinfo.m_numThreads = m_totalNumThreadsUsed - 1;
	m_threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000;
	m_threadPool = new hkCpuJobThreadPool(m_threadPoolCinfo);

	m_jobQueueInfo.m_jobQueueHwSetup.m_numCpuThreads = m_totalNumThreadsUsed;
	m_jobQueue = new hkJobQueue(m_jobQueueInfo);
	
	hkMonitorStream::getInstance().resize(200000);

	m_worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;
	m_worldInfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_REMOVE_ENTITY;
	m_physicsWorld = new hkpWorld(m_worldInfo);
	
	#ifdef _DEBUG
		m_physicsWorld->m_wantDeactivation = false;
	#endif

	m_physicsWorld->markForWrite();
	
	hkpAgentRegisterUtil::registerAllAgents(m_physicsWorld->getCollisionDispatcher());
	m_physicsWorld->registerWithJobQueue(m_jobQueue);
	
	m_context = new hkpPhysicsContext();
	hkpPhysicsContext::registerAllPhysicsProcesses();
	m_context->addWorld(m_physicsWorld);
	m_contextsArray.pushBack(m_context);

	m_physicsWorld->unmarkForWrite();

	m_vbd = new hkVisualDebugger(m_contextsArray);
	m_vbd->serve();
}

void Physics::deinit()
{
	{
		m_physicsWorld->markForWrite();
		m_physicsWorld->removeReference();
	}

	m_vbd->removeReference();
	m_context->removeReference();

	delete m_jobQueue;

	m_threadPool->removeReference();

	m_contextsArray.clearAndDeallocate();

	hkBaseSystem::quit();
	hkMemoryInitUtil::quit();
}

void Physics::stepSimulation(float dt)
{
	m_physicsWorld->stepMultithreaded(m_jobQueue, m_threadPool, dt);

	m_context->syncTimers(m_threadPool);
	m_vbd->step();

	hkMonitorStream::getInstance().reset();
	m_threadPool->clearTimerData();
}

hkpWorld *Physics::getWorld()
{
	return m_physicsWorld;
}

Main.cpp

#include "Physics.h"

int main()
{
	Physics *physic = new Physics();

	delete physic;
}

I've tried to follow ConsoleExampleMt, but still with no luck.
Thank you in advance.

Best Reply

Hi,do you get the same issue if you move thehkBaseSystem::quit(); to the end of you main function?-Vincent

No it solved the problem, but why?
Thank you :)

Due to the way C++ works, the actual destruction ofm_contextsArray will take place between the end of deinit and the return to the main function.The base system must still exists for the destruction ofm_contextsArray to take place, so the base system can only be removed outside of the physics class.-Vincent

Thank you both very much.
It helped me alot.
Have a nice day

-Peter

I've been having this problem too. I'm using the exact same Havok initialization and deinitialization code as the thread creator.

MovinghkBaseSystem::quit(); out of the physics class seemed to solve the problem, but now I'm getting a different crash.

I'm getting an error saying:
R6025
- pure virtual function call

Here's the call stack:

>	msvcr100d.dll!_NMSG_WRITE(int rterrnum) Line 217	C
msvcr100d.dll!_purecall() Line 54 + 0x7 bytes	C
Joined.exe!hkStackTracer::CallTree::quit() Line 25	C++
Joined.exe!hkMultiThreadCheck::staticQuit() Line 44	C++
Joined.exe!hkBaseSystem::quit() Line 390	C++

How should I prevent this crash from occuring?

I'm sorry to bring this thread back from the dead, but I'm having the same issue as the previous poster. I have movedhkBaseSystem::quit() to the bottom of the physics.TidyUp function. I'm using Ogre with Havok, as I presume the previous poster was aswell.

void Physics::TidyUp(void)
{
        physicsWorld->markForWrite();
	physicsWorld->removeReference();
	

	if( m_bVisualDebuggerActive )
	{
		m_pPhysicsContext->removeReference();
		m_pVisualDebugger->removeReference();
	}
	delete jobQueue;
	//
	// Clean up the thread pool
	//

	threadPool->removeReference();
	m_arrayPhysicsContext.clearAndDeallocate();

	#if defined HK_PLATFORM_PS3_PPU
		extern void quitSpurs( CellSpurs* spurs );
		quitSpurs( spurs );
	#endif
	
        hkMemoryInitUtil::quit();
	hkBaseSystem::quit();
}

The solution above is misleading/wrong. You should be shutting down the memory system last.
Try calling hkBaseSystem::quit() before hkMemoryInitUtil::quit(). Even better, move hkMemoryInitUtil::quit() to the very last line in main(). If you're still having problems please post the full, exact callstack and all of your Havok-related initialization code.

Cheers,
Tyler

Thanks, solved it.

Leave a Comment

Please sign in to add a comment. Not a member? Join today