pure virtual function call when linking statically
Moderators: CEGUI MVP, CEGUI Team
-
- Just popping in
- Posts: 8
- Joined: Mon Jan 19, 2009 14:20
- Location: Russia, Novocherkassk
- Contact:
pure virtual function call when linking statically
Hi,
I have a problem when statically linking CEGUI (0.6.1)
I got an error:
R6025
- pure virtual function call
which occur when my app (based on DXUT framework) is perform cleanup at the end:
void CALLBACK OnDestroyDevice(void* pUserContext)
{
SAFE_DELETE(mySystem); <- here i got error (mySystem is CEGUI::System*)
SAFE_DELETE(myRenderer);
}
And how can i get step into source code? I use static liblraries with "_d" but i cant step into destructor and see what happen (I have a source code of CEGUI either, maybe i should target it? how?).
If i change my app for use dynamic libraries of CEGUI everything works fine. (but i badly need static linking)
I have a problem when statically linking CEGUI (0.6.1)
I got an error:
R6025
- pure virtual function call
which occur when my app (based on DXUT framework) is perform cleanup at the end:
void CALLBACK OnDestroyDevice(void* pUserContext)
{
SAFE_DELETE(mySystem); <- here i got error (mySystem is CEGUI::System*)
SAFE_DELETE(myRenderer);
}
And how can i get step into source code? I use static liblraries with "_d" but i cant step into destructor and see what happen (I have a source code of CEGUI either, maybe i should target it? how?).
If i change my app for use dynamic libraries of CEGUI everything works fine. (but i badly need static linking)
Are you using the precompiled files? Pretty sure none of the precompiled files have any PDB information in them, because their file sizes are way too low; likely for distribution purposes. And there are obviously no PDB files supplied with the precompiled download.
Since you already have the source, you should only need to compile a debug build yourself. Just make sure you either use option C7 to compile the PDB info into your object files, or if you use Ci make sure the generated PDB file is sitting next to the lib you are linking against.
Since you already have the source, you should only need to compile a debug build yourself. Just make sure you either use option C7 to compile the PDB info into your object files, or if you use Ci make sure the generated PDB file is sitting next to the lib you are linking against.
- CrazyEddie
- CEGUI Project Lead
- Posts: 6760
- Joined: Wed Jan 12, 2005 12:06
- Location: England
- Contact:
With regards tot he original issue, when you built your app did you remember to define the CEGUI_STATIC preprocessor symbol?
If you are still looking to step into, or otherwise debug CEGUI, then as Jamarr says, compiling CEGUI yourself is definitely the way to go here.
I think the only precompiled version that's got the debug database is the VC++ 7.1 version, and this is likely why it's so huge (and why we wish to discontinue it!).
CE.
If you are still looking to step into, or otherwise debug CEGUI, then as Jamarr says, compiling CEGUI yourself is definitely the way to go here.
I think the only precompiled version that's got the debug database is the VC++ 7.1 version, and this is likely why it's so huge (and why we wish to discontinue it!).
CE.
Useful Links: Forum Guidelines | Documentation | Tutorials | HOWTO | Videos | Donate to CEGUI | CEGUI Twitter
- CrazyEddie
- CEGUI Project Lead
- Posts: 6760
- Joined: Wed Jan 12, 2005 12:06
- Location: England
- Contact:
anthony wrote:But there is already precompiled debug versions of dll's (for vc8).
Its not 'right' debug versions?
Yes, these are the "right" ones - it's just that the packages do not contain all the information to debug into CEGUI itself (which is not the purpose of them; it's to enable correct linking of your client code to the CEGUI libs, because having matching C/C++ runtime and other options for all components is very important).
It's highly unlikely there is an issue within CEGUI itself relating to pure virtual calls, because if there were we would have heard about it (a thousand times over) by now
Looking at other threads here on the forum, apparently deleting things twice can sometimes cause this. Because it's only happening on a static build, I might guess that it's related to cleaning up of modules (like the XML parser and so on), which is handled differently in static link situations (though I can not be sure).
I do not currently have a great deal of (any?) experience of CEGUI in statically linked situations, so I'm limited in what I can suggest, without resorting to talking about things I know nothing about
CE.
Useful Links: Forum Guidelines | Documentation | Tutorials | HOWTO | Videos | Donate to CEGUI | CEGUI Twitter
-
- Just popping in
- Posts: 8
- Joined: Mon Jan 19, 2009 14:20
- Location: Russia, Novocherkassk
- Contact:
I found problem in the compatibility with the DXUT.
Here is my minimal app:
Here is my minimal app:
Code: Select all
#include "stdafx.h"
#include "ceguitest.h"
#include "DXUT.h"
#include "CEGUIsystem.h"
#include "CEGUIWindow.h"
#include "CEGUIScheme.h"
#include "CEGUIImageset.h"
#include "CEGUIWindowManager.h"
#include "CEGUISchemeManager.h"
#include "CEGUIFontManager.h"
#include "falagard/CEGUIFalWidgetLookManager.h"
#include "CEGUIDefaultResourceProvider.h"
#include "d3d9renderer.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dxerr9.lib")
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "winmm.lib")
#ifdef _DEBUG
#pragma comment(lib, "freetype_d.lib")
#pragma comment(lib, "pcre_d.lib")
#pragma comment(lib, "expat_d.lib")
#pragma comment(lib, "CEGUIBase_Static_d.lib")
#pragma comment(lib, "CEGUIExpatParser_Static_d.lib")
#pragma comment(lib, "DirectX9GUIRenderer_Static_d.lib")
#pragma comment(lib, "CEGUIFalagardWRBase_Static_d.lib")
#else
#pragma comment(lib, "freetype.lib")
#pragma comment(lib, "pcre.lib")
#pragma comment(lib, "expat.lib")
#pragma comment(lib, "CEGUIBase_Static.lib")
#pragma comment(lib, "CEGUIExpatParser_Static.lib")
#pragma comment(lib, "DirectX9GUIRenderer_Static.lib")
#pragma comment(lib, "CEGUIFalagardWRBase_Static.lib")
#endif
CEGUI::DirectX9Renderer *myRenderer;
CEGUI::System *mySystem;
HRESULT CALLBACK OnCreateDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext)
{
using namespace CEGUI;
myRenderer = new DirectX9Renderer(pd3dDevice, 0);
myRenderer->preD3DReset();
mySystem = new System(myRenderer);
DefaultResourceProvider* rp = static_cast<DefaultResourceProvider*>(System::getSingleton().getResourceProvider());
rp->setResourceGroupDirectory("schemes", "./datafiles/schemes/");
rp->setResourceGroupDirectory("imagesets", "./datafiles/imagesets/");
rp->setResourceGroupDirectory("fonts", "./datafiles/fonts/");
rp->setResourceGroupDirectory("looknfeels", "./datafiles/looknfeel/");
rp->setResourceGroupDirectory("layouts", "./datafiles/layouts/");
// set the default resource groups to be used
Imageset::setDefaultResourceGroup("imagesets");
Font::setDefaultResourceGroup("fonts");
Scheme::setDefaultResourceGroup("schemes");
WidgetLookManager::setDefaultResourceGroup("looknfeels");
WindowManager::setDefaultResourceGroup("layouts");
SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");
WindowManager& wmgr = WindowManager::getSingleton();
Window* myRoot = wmgr.createWindow("DefaultWindow", "root");
System::getSingleton().setGUISheet(myRoot);
Window* fWnd = wmgr.createWindow("TaharezLook/FrameWindow", "Window");
myRoot->addChildWindow(fWnd);
return S_OK;
}
HRESULT CALLBACK OnResetDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext)
{
myRenderer->postD3DReset();
return S_OK;
}
void CALLBACK OnLostDevice(void* pUserContext)
{
myRenderer->preD3DReset();
}
void CALLBACK OnDestroyDevice(void* pUserContext)
{
//SAFE_DELETE(mySystem); // i got crash here
//SAFE_DELETE(myRenderer);
}
void CALLBACK OnFrameRender(IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext)
{
pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET, 0xff707070, 1.0f, 0);
pd3dDevice->BeginScene();
mySystem->renderGUI();
pd3dDevice->EndScene();
return;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
DXUTInit( TRUE, TRUE );
DXUTCreateWindow( L"DXUTTest" );
DXUTSetCallbackD3D9DeviceCreated(OnCreateDevice);
DXUTSetCallbackD3D9DeviceReset(OnResetDevice);
DXUTSetCallbackD3D9DeviceLost(OnLostDevice);
DXUTSetCallbackD3D9DeviceDestroyed(OnDestroyDevice);
DXUTSetCallbackD3D9FrameRender(OnFrameRender);
DXUTCreateDevice(true, 800, 600);
DXUTMainLoop();
SAFE_DELETE(mySystem); // here its all ok!
SAFE_DELETE(myRenderer);
return DXUTGetExitCode();
// after that static DXUT framework objects starts to destroy and OnLostDevice and OnDestroyDevice pair will be called but something required already destroyed(?) and we get virtual pure call. any ideas how to avoid it?
}
-
- Just popping in
- Posts: 8
- Joined: Mon Jan 19, 2009 14:20
- Location: Russia, Novocherkassk
- Contact:
here is this small solution for VS 2005
http://rapidshare.com/files/207545673/c ... t.zip.html
http://rapidshare.com/files/207545673/c ... t.zip.html
- CrazyEddie
- CEGUI Project Lead
- Posts: 6760
- Joined: Wed Jan 12, 2005 12:06
- Location: England
- Contact:
What you could do is test to see if the system object is already destroyed before deleting it:
If you want me to look at / test the solution posted, it will have to wait until the weekend at the earliest, and even then I can't guarantee anything
CE.
Code: Select all
if (CEGUI::System::getSingletonPtr())
// destroy system here
If you want me to look at / test the solution posted, it will have to wait until the weekend at the earliest, and even then I can't guarantee anything
CE.
Useful Links: Forum Guidelines | Documentation | Tutorials | HOWTO | Videos | Donate to CEGUI | CEGUI Twitter
-
- Just popping in
- Posts: 8
- Joined: Mon Jan 19, 2009 14:20
- Location: Russia, Novocherkassk
- Contact:
CrazyEddie wrote:What you could do is test to see if the system object is already destroyed before deleting it:Code: Select all
if (CEGUI::System::getSingletonPtr())
// destroy system here
If you want me to look at / test the solution posted, it will have to wait until the weekend at the earliest, and even then I can't guarantee anything
CE.
Yes, I understand that. Anyway thanks for help!
- CrazyEddie
- CEGUI Project Lead
- Posts: 6760
- Joined: Wed Jan 12, 2005 12:06
- Location: England
- Contact:
I did some testing with the posted VC++ project and get the same result (this was with vc9 and CEGUI 0.6.2 SDK, mainly because that's what I have on the VM I'm using).
The callstack indicates that the issue actually happens when destroying Window objects:
So I wonder if some statically created object is getting destroyed out of turn somewhere? Even if that is the case, I don't know how to fix that at the moment.
I'll rebuild and retest with a CEGUI built from source in order to drill a bit deeper.
CE
The callstack indicates that the issue actually happens when destroying Window objects:
Code: Select all
> ceguitest.exe!CEGUI::WindowManager::cleanDeadPool() + 0x1b3 bytes
ceguitest.exe!CEGUI::System::~System() + 0x15e bytes
ceguitest.exe!CEGUI::System::`vector deleting destructor'() + 0x2b bytes
ceguitest.exe!OnDestroyDevice(void * pUserContext=0x00000000) Line 95 + 0x3f bytes C++
ceguitest.exe!DXUTCleanup3DEnvironment9(bool bReleaseSettings=true) Line 3340 + 0x12 bytes C++
ceguitest.exe!DXUTCleanup3DEnvironment(bool bReleaseSettings=true) Line 5605 + 0xa bytes C++
ceguitest.exe!DXUTShutdown(int nExitCode=0) Line 6273 + 0x7 bytes C++
ceguitest.exe!DXUTState::Destroy() Line 356 C++
ceguitest.exe!DXUTState::~DXUTState() Line 308 + 0x2b bytes C++
ceguitest.exe!DXUTState::`scalar deleting destructor'() + 0x2b bytes C++
ceguitest.exe!DXUTDestroyState() Line 575 + 0x36 bytes C++
ceguitest.exe!DXUTMemoryHelper::~DXUTMemoryHelper() Line 588 C++
ceguitest.exe!`GetDXUTState'::`2'::`dynamic atexit destructor for 'memory''() + 0x28 bytes C++
So I wonder if some statically created object is getting destroyed out of turn somewhere? Even if that is the case, I don't know how to fix that at the moment.
I'll rebuild and retest with a CEGUI built from source in order to drill a bit deeper.
CE
Useful Links: Forum Guidelines | Documentation | Tutorials | HOWTO | Videos | Donate to CEGUI | CEGUI Twitter
- CrazyEddie
- CEGUI Project Lead
- Posts: 6760
- Joined: Wed Jan 12, 2005 12:06
- Location: England
- Contact:
I can confirm this is/was caused by the static objects CEGUI uses getting destroyed by the c/c++ runtime up before the call was made to perform application cleanup.
The solution is to explicitly call the DXUTShutdown() function in your application main function as opposed to just falling through at the end.
CE.
The solution is to explicitly call the DXUTShutdown() function in your application main function as opposed to just falling through at the end.
CE.
Useful Links: Forum Guidelines | Documentation | Tutorials | HOWTO | Videos | Donate to CEGUI | CEGUI Twitter
-
- Just popping in
- Posts: 8
- Joined: Mon Jan 19, 2009 14:20
- Location: Russia, Novocherkassk
- Contact:
CrazyEddie wrote:I can confirm this is/was caused by the static objects CEGUI uses getting destroyed by the c/c++ runtime up before the call was made to perform application cleanup.
The solution is to explicitly call the DXUTShutdown() function in your application main function as opposed to just falling through at the end.
CE.
Yes, this is a solution.
Im wonder, but if link CEGUI dynamically, this error doesn't appear.
Thank you.
- CrazyEddie
- CEGUI Project Lead
- Posts: 6760
- Joined: Wed Jan 12, 2005 12:06
- Location: England
- Contact:
There are inevitably some differences in how things are handled between statically and dynamically linked apps, much of which will be implementation defined.
There can never be any guarantees as regards to what happens when you fall-through main, and subsequently calling back into 'user' code when this happens is fraught with danger.
For my money, the fact it 'works' in a dynamically linked app is just pure luck and is a behaviour that should not be relied upon.
CE.
There can never be any guarantees as regards to what happens when you fall-through main, and subsequently calling back into 'user' code when this happens is fraught with danger.
For my money, the fact it 'works' in a dynamically linked app is just pure luck and is a behaviour that should not be relied upon.
CE.
Useful Links: Forum Guidelines | Documentation | Tutorials | HOWTO | Videos | Donate to CEGUI | CEGUI Twitter
Return to “Modifications / Integrations / Customisations”
Who is online
Users browsing this forum: No registered users and 12 guests