Trouble getting Havok set up

Trouble getting Havok set up

I'm trying to get Havok set up for the first time and it's giving me some trouble.  My main problem is that it's crashing, but let me go through the whole process in case some of it is meaningful.  I've been trying to copy the bulk of the stand alone console demo into my project to get Havok working.  At first I was trying to link to the FullDebug libs and it couldn't find the PDB's for some reason.  It would still run, but very slowly (possibly my fault, I think I fixed the slowdown later).  Eventually it would crash, but it looked like it was breaking in MyGUI somewhere.  I haven't done much multithreaded programming, so I didn't think to switch threads and see where the main thread was.  I also had to comment out the hkBaseSystem::quit() and hkMemoryInitUtil::quit() calls or it would crash on exit.  Today I switched to linking to the Debug libs and it doesn't complain about missing PDBs anymore.  I tinkered around with my code a little and it runs fine now, but it still crashes after 10-15 seconds in the same manner as before with the message:

Unhandled exception at 0x06972e06 in Engine.exe: 0xC0000005: Access violation reading location 0x000006f8.

I also finally thought to check the main thread and it seems to be crashing during m_physicsWorld->stepMultithreaded(m_jobQueue, m_threadPool, FIXED_TIMESTEP).  The jobQueue and threadPool look to be valid.  It appears to always crash at the same point.  I can see three messages pop up in the console about objects being removed and immediately after the third message it crashes.  The scene looks fine in the Visual Debugger as far as I can tell.

Edit: Ok, I think I figured out what the crash during runtime was all about.  The first two objects fall out of the world on the main thread.  The third object falling out of the world seems to be happening on a worker thread, which calls the error report callback, which I set up to send the message to my log manager.  The log manager also passes the message along to the Console window, which adds the text to the window through MyGUI, which I think does something with OpenGL and since this is on the Havok worker thread and not the thread I set OpenGL up on, it barfs and dies.  I think I can fix that.  It does still crash on exit if I don't comment out hkBaseSystem::quit() and hkMemoryInitUtil::quit() when I'm shutting down the physics manager.  And I haven't tried switching back to the FullDebug libs, but I suspect that will still complain about not being able to find the PDB's despite them being right there.  So answers to those questions would be appreciated.

Here is the code I modified from the stand alone demo:

#include "PhysicsMgr.h"
#include "LogMgr.h"
// Math and base include
#include <Common/Base/hkBase.h>
#include <Common/Base/System/hkBaseSystem.h>
#include <Common/Base/System/Error/hkDefaultError.h>
#include <Common/Base/Memory/System/Util/hkMemoryInitUtil.h>
#include <Common/Base/Monitor/hkMonitorStream.h>
#include <Common/Base/Memory/System/hkMemorySystem.h>
#include <Common/Base/Memory/Allocator/Malloc/hkMallocAllocator.h>
// Dynamics includes
#include <Physics/Collide/hkpCollide.h> 
#include <Physics/Collide/Agent/ConvexAgent/SphereBox/hkpSphereBoxAgent.h> 
#include <Physics/Collide/Shape/Convex/Box/hkpBoxShape.h> 
#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h> 
#include <Physics/Collide/Dispatch/hkpAgentRegisterUtil.h>
#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastInput.h> 
#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastOutput.h>
#include <Physics/Dynamics/World/hkpWorld.h> 
#include <Physics/Dynamics/Entity/hkpRigidBody.h> 
#include <Physics/Utilities/Dynamics/Inertia/hkpInertiaTensorComputer.h>
#include <Common/Base/Thread/Job/ThreadPool/Cpu/hkCpuJobThreadPool.h>
#include <Common/Base/Thread/Job/ThreadPool/Spu/hkSpuJobThreadPool.h>
#include <Common/Base/Thread/JobQueue/hkJobQueue.h>
// Visual Debugger includes
#include <Common/Visualize/hkVisualDebugger.h>
#include <Physics/Utilities/VisualDebugger/hkpPhysicsContext.h>
// Keycode
#include <Common/Base/keycode.cxx>
#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
// This excludes libraries that are not going to be linked
// from the project configuration, even if the keycodes are
// present
#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
#undef HK_FEATURE_PRODUCT_NEW_PHYSICS
#define HK_FEATURE_REFLECTION_PHYSICS
#define HK_CLASSES_FILE <Common/Serialize/Classlist/hkClasses.h>
#define HK_EXCLUDE_FEATURE_MemoryTracker
#define HK_EXCLUDE_FEATURE_SerializeDeprecatedPre700
#define HK_EXCLUDE_FEATURE_RegisterVersionPatches 
#define HK_EXCLUDE_LIBRARY_hkGeometryUtilities
#include <Common/Base/Config/hkProductFeatures.cxx>
#include <string>
#include <sstream>
static void errorReport(const char* msg, void* userArgGivenToInit)
{
 LOG_WRITE(LogMgr::PHYSICS, msg);
}
const float PhysicsMgr::ACCUMULATOR_MAX = 2.0f/60.0f;
const float PhysicsMgr::FIXED_TIMESTEP = 1.0f/60.0f;
PhysicsMgr::PhysicsMgr(void)
{
 m_threadPool = nullptr;
 m_jobQueue = nullptr;
 m_physicsWorld = nullptr;
 m_accumulator = 0.0f;
#ifdef DEBUG
 m_vdbContext = nullptr;
 m_vdb = nullptr;
#endif
}
PhysicsMgr::~PhysicsMgr(void)
{
 close();
}
void PhysicsMgr::init(void)
{
 close();
//
 // Initialize the base system including our memory system
 //
 // Allocate 0.5MB of physics solver buffer.
 hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault(hkMallocAllocator::m_defaultMallocAllocator, hkMemorySystem::FrameInfo(500 * 1024));
 hkBaseSystem::init(memoryRouter, errorReport);
 {
 //
 // Initialize the multi-threading classes, hkJobQueue, and hkJobThreadPool
 //
// They can be used for all Havok multithreading tasks. In this exmaple we only show how to use
 // them for physics, but you can reference other multithreading demos in the demo framework
 // to see how to multithread other products. The model of usage is the same as for physics.
 // The hkThreadpool has a specified number of threads that can run Havok jobs. These can work
 // alongside the main thread to perform any Havok multi-threadable computations.
 // The model for running Havok tasks in Spus and in auxilary threads is identical. It is encapsulated in the
 // class hkJobThreadPool. On PlayStation(R)3 we initialize the SPU version of this class, which is simply a SPURS taskset.
 // On other multi-threaded platforms we initialize the CPU version of this class, hkCpuJobThreadPool, which creates a pool of threads
 // that run in exactly the same way. On the PlayStation(R)3 we could also create a hkCpuJobThreadPool. However, it is only
 // necessary (and advisable) to use one Havok PPU thread for maximum efficiency. In this case we simply use this main thread
 // for this purpose, and so do not create a hkCpuJobThreadPool.
//hkJobThreadPool* m_threadPool;
// We can cap the number of threads used - here we use the maximum for whatever multithreaded platform we are running on. This variable is
 // set in the following code sections.
 int totalNumThreadsUsed;
// Get the number of physical threads available on the system
 hkHardwareInfo hwInfo;
 hkGetHardwareInfo(hwInfo);
 totalNumThreadsUsed = hwInfo.m_numThreads;
// We use one less than this for our thread pool, because we must also use this thread for our simulation
 hkCpuJobThreadPoolCinfo threadPoolCinfo;
 threadPoolCinfo.m_numThreads = totalNumThreadsUsed - 1;
// This line enables timers collection, by allocating 200 Kb per thread. If you leave this at its default (0),
 // timer collection will not be enabled.
 threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000;
 m_threadPool = new hkCpuJobThreadPool(threadPoolCinfo);
// We also need to create a Job queue. This job queue will be used by all Havok modules to run multithreaded work.
 // Here we only use it for physics.
 hkJobQueueCinfo info;
 info.m_jobQueueHwSetup.m_numCpuThreads = totalNumThreadsUsed;
 //hkJobQueue* jobQueue = new hkJobQueue(info);
 m_jobQueue = new hkJobQueue(info);
//
 // Enable monitors for this thread.
 //
// Monitors have been enabled for thread pool threads already (see above comment).
 hkMonitorStream::getInstance().resize(200000);
//
 // <PHYSICS-ONLY>: Create the physics world.
 // At this point you would initialize any other Havok modules you are using.
 //
 //hkpWorld* physicsWorld;
 {
 // The world cinfo contains global simulation parameters, including gravity, solver settings etc.
 hkpWorldCinfo worldInfo;
// Set the simulation type of the world to multi-threaded.
 worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;
// Flag objects that fall "out of the world" to be automatically removed - just necessary for this physics scene
 worldInfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_REMOVE_ENTITY;
m_physicsWorld = new hkpWorld(worldInfo);
#if DEBUG
 // Disable deactivation, so that you can view timers in the VDB. This should not be done in your game.
 //m_physicsWorld->m_wantDeactivation = false;
#endif
 // When the simulation type is SIMULATION_TYPE_MULTITHREADED, in the debug build, the sdk performs checks
 // to make sure only one thread is modifying the world at once to prevent multithreaded bugs. Each thread
 // must call markForRead / markForWrite before it modifies the world to enable these checks.
 m_physicsWorld->markForWrite();
 // Register all collision agents, even though only box - box will be used in this particular example.
 // It's important to register collision agents before adding any entities to the world.
 hkpAgentRegisterUtil::registerAllAgents(m_physicsWorld->getCollisionDispatcher());
// We need to register all modules we will be running multi-threaded with the job queue
 m_physicsWorld->registerWithJobQueue(m_jobQueue);
// Create all the physics rigid bodies
 setupTestPhysics(m_physicsWorld);
 }
#ifdef DEBUG
 //
 // Initialize the VDB
 //
 //hkArray<hkProcessContext*> contexts;
// <PHYSICS-ONLY>: Register physics specific visual debugger processes
 // By default the VDB will show debug points and lines, however some products such as physics and cloth have additional viewers
 // that can show geometries etc and can be enabled and disabled by the VDB app.
 //hkpPhysicsContext* context;
 {
 // The visual debugger so we can connect remotely to the simulation
 // The context must exist beyond the use of the VDB instance, and you can make
 // whatever contexts you like for your own viewer types.
 m_vdbContext = new hkpPhysicsContext();
 hkpPhysicsContext::registerAllPhysicsProcesses(); // all the physics viewers
 m_vdbContext->addWorld(m_physicsWorld); // add the physics world so the viewers can see it
 m_vdbContexts.pushBack(m_vdbContext);
 }
#endif
// Now we have finished modifying the world, release our write marker.
 m_physicsWorld->unmarkForWrite();
#ifdef DEBUG
 //hkVisualDebugger* vdb = new hkVisualDebugger(m_vdbContexts);
 m_vdb = new hkVisualDebugger(m_vdbContexts);
 m_vdb->serve();
#endif
} 
}
void PhysicsMgr::close(void)
{
 if (m_physicsWorld != nullptr)
 {
 m_physicsWorld->markForWrite();
 m_physicsWorld->removeReference();
 }
#ifdef DEBUG
 if (m_vdb != nullptr)
 {
 m_vdb->removeReference();
 }
// Contexts are not reference counted at the base class level by the VDB as
 // they are just interfaces really. So only delete the context after you have
 // finished using the VDB.
 if (m_vdbContext != nullptr)
 {
 m_vdbContext->removeReference();
 }
#endif
if (m_jobQueue != nullptr)
 {
 delete m_jobQueue;
 m_jobQueue = nullptr;
 }
//
 // Clean up the thread pool
 //
 if (m_threadPool != nullptr)
 {
 m_threadPool->removeReference();
 }
if (hkBaseSystem::isInitialized())
 {
 //TODO: figure out why calling these crashes on exit and fix it
 //hkBaseSystem::quit();
 //hkMemoryInitUtil::quit();
 }
}
void PhysicsMgr::update(float _dt)
{
 //TODO: check the userguide for what they suggest to deal with variable timesteps, but I assume I should be accumulating until I have a timestep the size of the frequency I want and then step once.
 m_accumulator += _dt;
 if (m_accumulator > ACCUMULATOR_MAX)
 {
 m_accumulator = ACCUMULATOR_MAX;
 LOG_WARN("PhysicsMgr timestep accumulator hit max value, physics simulation is going to get funky.");
 }
//std::stringstream out;
 //out << m_accumulator;
 //std::string str = "Accumulator: " + out.str();
 //std::stringstream out2;
 //out2 << _dt;
 //str += " dT: " + out2.str();
 //LOG_INFO(str);
 while (m_accumulator >= FIXED_TIMESTEP)
 {
 // <PHYSICS-ONLY>:
 // Step the physics world. This single call steps using this thread and all threads
 // in the threadPool. For other products you add jobs, call process all jobs and wait for completion.
 // See the multithreading chapter in the user guide for details
 m_physicsWorld->stepMultithreaded(m_jobQueue, m_threadPool, FIXED_TIMESTEP);
 m_accumulator -= FIXED_TIMESTEP;
#ifdef DEBUG
 // Step the visual debugger. We first synchronize the timer data
 m_vdbContext->syncTimers(m_threadPool);
 m_vdb->step();
#endif
// Clear accumulated timer data in this thread and all slave threads
 hkMonitorStream::getInstance().reset();
 m_threadPool->clearTimerData();
 }
}
//------------------------------------------Testing------------------------------------------//
void createBrickWall( hkpWorld* world, int height, int length, const hkVector4& position, hkReal gapWidth, hkpConvexShape* box, hkVector4Parameter halfExtents )
{
 hkVector4 posx = position;
 // do a raycast to place the wall
 {
 hkpWorldRayCastInput ray;
 ray.m_from = posx;
 ray.m_to = posx;
ray.m_from(1) += 20.0f;
 ray.m_to(1) -= 20.0f;
hkpWorldRayCastOutput result;
 world->castRay( ray, result );
 posx.setInterpolate4( ray.m_from, ray.m_to, result.m_hitFraction );
 }
 // move the start point
 posx(0) -= ( gapWidth + 2.0f * halfExtents(0) ) * length * 0.5f;
 posx(1) -= halfExtents(1) + box->getRadius();
hkArray<hkpEntity*> entitiesToAdd;
for ( int x = 0; x < length; x ++ ) // along the ground
 {
 hkVector4 pos = posx;
 for( int ii = 0; ii < height; ii++ )
 {
 pos(1) += (halfExtents(1) + box->getRadius())* 2.0f;
hkpRigidBodyCinfo boxInfo;
 boxInfo.m_mass = 10.0f;
 hkMassProperties massProperties;
 hkpInertiaTensorComputer::computeBoxVolumeMassProperties(halfExtents, boxInfo.m_mass, massProperties);
boxInfo.m_mass = massProperties.m_mass;
 boxInfo.m_centerOfMass = massProperties.m_centerOfMass;
 boxInfo.m_inertiaTensor = massProperties.m_inertiaTensor;
 boxInfo.m_solverDeactivation = boxInfo.SOLVER_DEACTIVATION_MEDIUM;
 boxInfo.m_shape = box;
 //boxInfo.m_qualityType = HK_COLLIDABLE_QUALITY_DEBRIS;
 boxInfo.m_restitution = 0.0f;
boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
{
 boxInfo.m_position = pos;
 hkpRigidBody* boxRigidBody = new hkpRigidBody(boxInfo);
 world->addEntity( boxRigidBody );
 boxRigidBody->removeReference();
 }
pos(1) += (halfExtents(1) + box->getRadius())* 2.0f;
 pos(0) += halfExtents(0) * 0.6f;
 {
 boxInfo.m_position = pos;
 hkpRigidBody* boxRigidBody = new hkpRigidBody(boxInfo);
 entitiesToAdd.pushBack(boxRigidBody);
 }
 pos(0) -= halfExtents(0) * 0.6f;
 }
 posx(0) += halfExtents(0)* 2.0f + gapWidth;
 }
 world->addEntityBatch( entitiesToAdd.begin(), entitiesToAdd.getSize());
for (int i=0; i < entitiesToAdd.getSize(); i++){ entitiesToAdd[i]->removeReference(); }
}
hkpRigidBody* g_ball;
void setupPhysics(hkpWorld* physicsWorld)
{
 //
 // Create the ground box
 //
 {
 hkVector4 groundRadii( 70.0f, 2.0f, 140.0f );
 hkpConvexShape* shape = new hkpBoxShape( groundRadii , 0 );
hkpRigidBodyCinfo ci;
ci.m_shape = shape;
 ci.m_motionType = hkpMotion::MOTION_FIXED;
 ci.m_position = hkVector4( 0.0f, -2.0f, 0.0f );
 ci.m_qualityType = HK_COLLIDABLE_QUALITY_FIXED;
physicsWorld->addEntity( new hkpRigidBody( ci ) )->removeReference();
 shape->removeReference();
 }
hkVector4 groundPos( 0.0f, 0.0f, 0.0f );
 hkVector4 posy = groundPos;
//
 // Create the walls
 //
int wallHeight = 8;
 int wallWidth = 8;
 int numWalls = 6;
 hkVector4 boxSize( 1.0f, 0.5f, 0.5f);
 hkpBoxShape* box = new hkpBoxShape( boxSize , 0 );
 box->setRadius( 0.0f );
hkReal deltaZ = 25.0f;
 posy(2) = -deltaZ * numWalls * 0.5f;
for ( int y = 0; y < numWalls; y ++ ) // first wall
 {
 createBrickWall( physicsWorld, wallHeight, wallWidth, posy, 0.2f, box, boxSize );
 posy(2) += deltaZ;
 }
 box->removeReference();
//
 // Create a ball moving towards the walls
 //
const hkReal radius = 1.5f;
 const hkReal sphereMass = 150.0f;
hkVector4 relPos( 0.0f,radius + 0.0f, 50.0f );
hkpRigidBodyCinfo info;
 hkMassProperties massProperties;
 hkpInertiaTensorComputer::computeSphereVolumeMassProperties(radius, sphereMass, massProperties);
info.m_mass = massProperties.m_mass;
 info.m_centerOfMass = massProperties.m_centerOfMass;
 info.m_inertiaTensor = massProperties.m_inertiaTensor;
 info.m_shape = new hkpSphereShape( radius );
 info.m_position.setAdd4(posy, relPos );
 info.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
info.m_qualityType = HK_COLLIDABLE_QUALITY_BULLET;
 hkpRigidBody* sphereRigidBody = new hkpRigidBody( info );
 g_ball = sphereRigidBody;
physicsWorld->addEntity( sphereRigidBody );
 sphereRigidBody->removeReference();
 info.m_shape->removeReference();
hkVector4 vel( 0.0f,4.9f, -100.0f );
 sphereRigidBody->setLinearVelocity( vel );
}
//------------------------------------------Testing------------------------------------------//
void PhysicsMgr::setupTestPhysics(hkpWorld* _world)
{
 setupPhysics(_world);
}

7 Beiträge / 0 neu
Letzter Beitrag
Nähere Informationen zur Compiler-Optimierung finden Sie in unserem Optimierungshinweis.

Hi Apostate--

I would suggest trying to set Havok up in single-threaded mode before trying to use multiple threads. Aside from that, can you clearly enumerate the questions you have? It's rather difficult to parse out which issues have been fixed and which are still outstanding. Thanks.

--Tim

Sorry, I was kind of rushed when I posted originally.  It is kind of a mess of words, isn't it?  Anyway, I fixed the multithreading issue.  I still have three issues.

1) If I try to link to the FullDebug libs, the linker can't find the PDBs for Havok.  I get many messages of this sort for all of the Havok libs:

1>hkBase.lib(hk1AxisSweep.obj) : warning LNK4099: PDB 'hkbase.pdb' was not found with 'hkBase.lib(hk1AxisSweep.obj)' or at 'D:\Coding\EngineGit\Engine\bin\windows\debug\hkbase.pdb'; linking object as if no debug info
1>hkBase.lib(hkLineSegmentUtil.obj) : warning LNK4099: PDB 'hkbase.pdb' was not found with 'hkBase.lib(hkLineSegmentUtil.obj)' or at 'D:\Coding\EngineGit\Engine\bin\windows\debug\hkbase.pdb'; linking object as if no debug info
1>hkBase.lib(hkRadixSort.obj) : warning LNK4099: PDB 'hkbase.pdb' was not found with 'hkBase.lib(hkRadixSort.obj)' or at 'D:\Coding\EngineGit\Engine\bin\windows\debug\hkbase.pdb'; linking object as if no debug info

Not a huge deal, but I'd like it if it worked, just in case I need it later.  Linking to the Debug libs works fine.

2)This is also probably not that important, but in section 3.1 Asynchronous Stepping of the documentation, they make mention of a section titled "Stepping The Simulation Forward" that doesn't seem to exist anymore.  The only other reference I could find to it in the documentation was in section 2.5 Asynchronous Simulation, which also tells you to refer to a section called "Stepping The Simulation Forward".  It's mentioned on the forums in another post as supposedly being under Havok Physics > Havok Dynamics > Stepping the simulation forward, but Havok Dynamics isn't a section either.   Edit: I found it.  The section is just called "Stepping the Simulation" (2.3) and the topic is "Asynchronous Stepping" (2.3.4).  A little confusing that the names are slightly different.

3) Finally, my main issue is that I'm getting an assert during shutdown.  I'm probably not shutting down Havok correctly.  If I comment out hkBaseSystem::quit() and hkMemoryInitUtil::quit() in close(), which is called by the destructor for PhysicsMgr (on lines 214-215 above), I can make it go away, but that doesn't really solve the problem, just hide it.  The stack seems to indicate I've done something horrible with memory, but I haven't found what I'm doing differently from the demo.  Here is the stack as far as I can track it before it gets corrupted:

> Engine.exe!hkContainerHeapAllocator::Allocator::bufFree(void * p, int numBytes) Line 33 C++
Engine.exe!hkMemoryAllocator::_bufFree<hkProcessContext *>(void * p, int numElem) Line 182 + 0x1a bytes C++
Engine.exe!hkArrayBase<hkProcessContext *>::_clearAndDeallocate(hkMemoryAllocator & alloc) Line 175 C++
Engine.exe!hkArray<hkProcessContext *,hkContainerHeapAllocator>::clearAndDeallocate() Line 339 + 0x43 bytes C++
Engine.exe!hkArray<hkProcessContext *,hkContainerHeapAllocator>::~hkArray<hkProcessContext *,hkContainerHeapAllocator>() Line 527 C++
Engine.exe!PhysicsMgr::~PhysicsMgr() Line 85 + 0x12 bytes C++
Engine.exe!PhysicsMgr::`scalar deleting destructor'() + 0x2b bytes C++
Engine.exe!GameGlobals::close() Line 53 + 0x37 bytes C++
Engine.exe!GameGlobals::~GameGlobals() Line 21 C++
Engine.exe!GameGlobals::`scalar deleting destructor'() + 0x2b bytes C++
Engine.exe!Game::close() Line 78 + 0x37 bytes C++
Engine.exe!WndProc(HWND__ * hWnd, unsigned int message, unsigned int wParam, long lParam) Line 153 C++
user32.dll!76c462fa()
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
user32.dll!76c46d3a()
user32.dll!76c46ce9()
user32.dll!76c50d27()
user32.dll!76c50d4d()
opengl32.dll!5b5160fb()
user32.dll!76c462fa()
user32.dll!76c46d3a()
user32.dll!76c46ce9()
user32.dll!76c46de8()
user32.dll!76c46e44()
ntdll.dll!7798010a()
user32.dll!76c472b9()
user32.dll!76c474bb()
user32.dll!76c50d27()
user32.dll!76c50d4d()
opengl32.dll!5b5160fb()
user32.dll!76c46e44()
ntdll.dll!7798f8ca()
user32.dll!76c462fa()
user32.dll!76c46d3a()
user32.dll!76c46ce9()
user32.dll!76c46de8()
user32.dll!76c46e44()
ntdll.dll!7798010a()
user32.dll!76c472b9()
user32.dll!76c474bb()
user32.dll!76c50d27()
user32.dll!76c50d4d()
opengl32.dll!5b5160fb()
user32.dll!76c462fa()
user32.dll!76c47316()
user32.dll!76c46ce9()
user32.dll!76c46de8()
user32.dll!76c46e44()
ntdll.dll!7798010a()
user32.dll!76c472b9()
user32.dll!76c52161()
user32.dll!76c50d4d()
opengl32.dll!5b5160fb()
user32.dll!76c462fa()
user32.dll!76c46d3a()
user32.dll!76c46ce9()
ntdll.dll!7798010a()
user32.dll!76c50751()
user32.dll!76c4788a()
Engine.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 64 + 0xc bytes C++
Engine.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
Engine.exe!wWinMainCRTStartup() Line 371 C
kernel32.dll!750d33aa()
ntdll.dll!779a9ef2()
ntdll.dll!779a9ec5()

Hi Apostate--

Thanks for the clarifications. With respect to (1), this is expected behavior. In order to keep download sizes manageble, we do not distribute the .pdbs for FullDebug. The other configurations do provide pdbs, however, which might prove a reasonable alternative. For (2), I agree that it's confusing that the docs refer to a section by the wrong name. I've submitted a bug report to address this issue.

Based on the callstack you provide for the crash in (3), it looks like you have an hkArray member variable in your PhysicsMgr class (note that the callstack indicates a crash in the hkArray desctructor). Assuming that's true, then you destroying the Havok memory manager in close(), after which the PhysicsMgr destructor invokes destructors on all its members. One or more of these members is an hkArray whose memory was managed by the recently destroyed memory manager. This destructor tries to reference this manager and fails. Assuming this is the problem, you could use a different array for PhysicsMgr members, or put Havok startup/shutdown at a higher scope than the PhysicsMgr().

Please let me know how that works for you - thanks!

--Tim

That seems to have fixed it.  I had the hkArray<hkProcessContext*> that hkVisualDebugger uses in the header as a member of PhysicsMgr.  Do I need that for anything other than creating the hkVisualDebugger?  Is it safe to create it locally (around line 159) and let it go out of scope after the hkVisualDebugger is created?

Hi Apostate--

I'm glad that change fixed the crash. It is unfortunately not safe to give up your handles to the process contexts because the visual debugger (VDB) does not perform reference counting. If you call removeReference() on the context, it will be deleted, and if you simply lose track of your your pointers, you risk a memory leak. I suggest storing them in a std::vector<hkProcessContext*>, and calling clear() on this array after shutting down the VDB (m_vdbContext->removeReference();) but before calling quit(). Please let me know if you have any further questions - thanks!

--Tim

Yep, that's what I figured, but I wanted to make sure.  Thanks for all the help.

Kommentar hinterlassen

Bitte anmelden, um einen Kommentar hinzuzufügen. Sie sind noch nicht Mitglied? Jetzt teilnehmen