I'm creating a DirectX 11 helper class that looks kind of like this:
#import "DXClass.h" // I have declared the constructor and the other methods here
// All of the DirectX libraries are imported in the header as well
DXClass::DXClass()
{
// Pointers created, etc.
}
DXClass:~DXClass()
{
// Other DirectX objects released
// With an if (bbSRView) {}, the exception still occurs, so bbSRView is not NULL
// bbSRView is a ID3D11ShaderResourceView*
// When the other violation does not occur, one does here:
bbSRView->Release();
bbSRView = NULL;
// More releases
void DXClass::Initialize()
{
SetupDisplay();
// Other initialization that works fine
}
void DXClass::SetupDisplay()
{
// This is where the debugger shows the access violation.
// factory is declared as DXGIFactory*
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&factory);
// Loop through adapters and outputs, etc.
}
This class is initialized like this: dxClass = new DXClass();
The Initialize() function is called in another method of the class that created dxClass.
When the application is run, I get an access violation at the beginning of the setupDisplay() function. However, if I take the code in setupDisplay() and put it in Initialize(), removing the call to setupDisplay(), no access violation occurs. Also, if I remove the code from setupDisplay() so that it is an empty function, and then call it in Initialize(), no access violation occurs.
It appears that no pointers are NULL, and the application will start fine if it is changed as described above. However, on another note, the application receives another access violation when quitting. The debugger points to a Release() call on an ID3D11ShaderResourceView*, which I have pointed out in my code snippet. This pointer also appears to be valid.
I have also checked the similar questions, but the this pointer of the class appears to be valid, and I am not creating any buffers that could be overflowing. There also isn't anything that could be deleting/freeing the object early.
I have no idea what could be causing the errors. :/
Thanks :D
EDIT:
Here's an isolated test, with the same errors:
I have in my main function:
INT APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, INT)
{
App *app = new App();
app->Run();
app->Release();
}
In my App class, I have removed all window functionality and any other variables so that it looks like this:
App::App()
{
dxClass = new DXClass();
}
App::~App()
{
delete dxClass;
}
void App::Run()
{
dxClass->Initialize();
while (true) {} // Never reaches here
}
The access violation still occurs at the same place. Also, same results if I replace the factory instance variable with:
IDXGIFactory *f;
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&f);
Which has worked for me in other applications.
An access violation when calling Release() usually means the object has already received it's final Release() from somewhere else (and it has destroyed itself). One possible solution would be to AddRef() when passing the pointer into your DXClass
Related
I'm debugging an intermittent issue on a customer site. I've got it down to the point that it appears that a call to Release() on a COM object is not returning.
The first log is printing but I never see the second log. I can only assume that the call to Release() never returned for some reason (or could it be the CoInitializeEx()).
I have no idea what to look for next, any help/clues would be greatly appreciated.
Logger::getLogger()->logTrace("AudioCapturer::_shutdown. _pEndpointAudioClient_COM Released. (%s)", _deviceName.c_str());
releaseComObject(_pAudioCaptureClient_COM);
Logger::getLogger()->logTrace("AudioCapturer::_shutdown (%s) succeeded", _deviceName.c_str());
Here is the supporting code:
IAudioCaptureClient *_pAudioCaptureClient_COM;
// Class that Initializes COM on creation and Unitializes on destruction
AutoCOM::AutoCOM() { CoInitializeEx(NULL, COINIT_MULTITHREADED); }
AutoCOM::~AutoCOM() { CoUninitialize(); }
#define AUTO_COM_SUPPORT AutoCOM _autoCOM
// Safe releasing of COM objects. Zeros the pointer
// to the COM object. Safe to use with NULL
// pointers.
template <class T> void releaseComObject(T*& pT) {
if (pT) {
AUTO_COM_SUPPORT;
(pT)->Release();
pT = NULL;
}
}
Never found a duplication scenario for the issue. But the problem was averted with the user of smart pointers, which was mentioned by #Cheersandhth.-Alf. Thanks for the feedback.
Basically used the following macro to define smart pointers, and removed all references to Release()
_COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface));
I am upgrading an application from VC6 to VS2010 (Legacy Code). The application runs as it should in VC6 but after converting the project to VS2010 I encountered some problems.
On exiting the application, the program breaks while attempting to lock on entering a critical section.
The lock count usually alternates from -1(Unlocked) to -2(Locked) but just before the program crashes, the lock count is 0.
g_RenderTargetCriticalSection.Lock();// Breaks here
if (g_RenderTargets.Lookup(this, pRenderTarget))
{
ASSERT_VALID(pRenderTarget);
g_RenderTargets.RemoveKey(this);
delete pRenderTarget;
}
g_RenderTargetCriticalSection.Unlock();
Here is the CCriticalSection::Lock() function where ::EnterCriticalSection(&m_sect); fails. I found it strange that on failing, the lock count changes from 0 to -4??
_AFXMT_INLINE BOOL (::CCriticalSection::Lock())
{
::EnterCriticalSection(&m_sect);
return TRUE;
}
If anyone has encountered anything similar to this, some insight would be greatly appreciated. Thanks in advance.
The comments indicate this is a file-scope object destructor order issue. There are various ways you could address this. Since I haven't seen the rest of the code it's difficult to offer specific advice, but one idea is to change the CS to live in a shared_ptr and have your CWnd hold onto a copy so it won't be destroyed prematurely. e.g.:
std::shared_ptr<CCriticalSection> g_renderTargetCriticalSection(new CCriticalSection());
Then in your window class:
class CMyWindow : public CWnd
{
private:
std::shared_ptr<CCriticalSection> m_renderTargetCriticalSection;
public:
CMyWindow()
: m_renderTargetCriticalSection(g_renderTargetCriticalSection)
{
// ...
}
~CMyWindow()
{
// guaranteed to still be valid since our shared_ptr is keeping it alive
CSingleLock lock(m_renderTargetCriticalSection.get(), TRUE);
// ...
}
// ...
};
The issue was that the application's Main Window was being destroyed after the application's global object was destroyed. This meant that the g_renderTargetCriticalSection was already Null when the main window was trying to be destroyed.
The solution was to destroy the Application's main window before it's global object (CDBApp theApp) calls ExitInstance() and is destroyed.
int CDBApp::ExitInstance()
{
LOGO_RELEASE
//Destroy the Main Window before the CDBApp Object (theApp) is destroyed.
if(m_Instance.m_hWnd)
m_Instance.DestroyWindow();
return CWinApp::ExitInstance();
}
This code doesn't make sense:
int CDBApp::ExitInstance()
{
LOGO_RELEASE
//Destroy the Main Window before the CDBApp Object (theApp) is destroyed.
if(m_Instance.m_hWnd)
m_Instance.DestroyWindow();
return CWinApp::ExitInstance();
}
m_Instance is a handle, not a class, so it can't be used to call functions!
This is excerpt from my WinMain method. It is not complete but I think it is sufficient to illustrate core of problem. Please don't ask why I am deleting data module explicitly when it should be done automatically. This is entirely another issue (has to do with incorrect finalization order when application initialization ends prematurely with exception in one of constructors).
extern PACKAGE TDataModule_Local *DataModule_Local;
class TDataModule_Local :
public TDataModule
{
...
public:
__fastcall TDataModule_Local(TComponent *Owner);
__fastcall ~TDataModule_Local();
}
WINAPI wWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
Application->Initialize();
Application->CreateForm(__classid(TMainForm), &MainForm);
Application->CreateForm(__classid(TDataModule_Local), &DataModule_Local);
Application->Run();
if (DataModule_Local != NULL)
{
delete DataModule_Local; // destructor not called! why?
DataModule_Local = NULL;
}
return 0;
}
Whats weird destructor of data module is not called when I use delete operator. Is is called after program reaches enclosing brace of WinMain method:
You said
deleting data module explicitly when it should be done automatically
Obviously whatever code is designed to free it automatically is still trying to do so, blissfully ignorant of your problems with finalization order.
Just because you've set your pointer to NULL doesn't mean that there isn't a copy of the pointer sitting in a list of objects to be cleaned up on exit.
The MSDN documentation for the CCmdTarget::OnFinalRelease method is pretty brief:
Called by the framework when the last OLE reference to or from the
object is released.
I have created a sub-class of CCmdTarget
class CMyEventHandler : public CCmdTarget { ... }
I'm trying to figure out under what conditions the OnFinalRelease method will be called. I have some code that looks something like this:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
Using this code, I observe that the OnFinalRelease method is never called. This means I have a memory leak. So I modified the wrap-up code as follows:
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
delete myEventHandler;
myEventHandler = NULL;
This section of code is triggered off periodically throughout the day. What I notice now is that, while the destructor for the wrapped up instance of myEventHandler is called as expected, the OnFinalRelease function is getting called now! What's worse, it is being called not on the instance that has been wrapped up, but instead on a newly created instance of CMyEventHandler! Thinking that this might be due to a reference counting issue, I modified my wire-up and wrap-up code:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
delete myEventHandler;
myEventHandler = NULL;
I let this run all day and now observe that OnFinalRelease is never called. The destructor for the wrapped up instance is called as I would expect, but I'm left feeling uneasy as I clearly don't understand the circumstances under which OnFinalRelease is called. Is OnFinalRelease called on some delay, or is there a way to force it to fire? What will trigger OnFinalRelease to be called?
If it matters, the event source is a .NET assembly exposing events via COM interop.
With COM you should always use the CoCreateInstance() AddRef() and Release() paradigm to manage lifetime of your objects, and let COM do the destruction of your objects based on reference counts. Avoid new and delete because using them breaks this paradigm and causes interesting side effects. You probably have a bug in the management of the reference counts.
The way to debug why the reference counts are not being managed correctly is to override CCmdTarget::InternalRelease() copy the source from oleunk.cpp and put some trace output or break points.
DWORD CMyEventHandler::InternalRelease()
{
ASSERT(GetInterfaceMap() != NULL);
if (m_dwRef == 0)
return 0;
LONG lResult = InterlockedDecrement(&m_dwRef);
if (lResult == 0)
{
AFX_MANAGE_STATE(m_pModuleState);
OnFinalRelease();
}
return lResult;
}
There are lots of times when passing IDispatch interfaces that code will bump reference counts and you have to decrement the reference count using Release(). Pay attention to where your code may be passing this interface because there is aconvention in COM that when Interfaces are passed using [in] or [out] where the caller or callee has to release the interface.
When the reference count issue is corrected you shoudl see the objects OnFinalRelease code being called and the object destoryed by hte MFC framework:
For CCmdTarget the destruction should happen as a result of the final
release in the parent class CWnd:
void CWnd::OnFinalRelease()
{
if (m_hWnd != NULL)
DestroyWindow(); // will call PostNcDestroy
else
PostNcDestroy();
}
FYI: Passing interfaces across threads without marshalling the interface pointers is another common reason to get errors in COM.
It doesn't appear that you ever call myEventHandler->Release(). Therefore, the last reference is never released, and OnFinalRelease is never called.
Program works fine (with random crashes) and Memory Validator reports Uninitialized read problem in pD3D = Direct3DCreate9.
What could be the problem ?
init3D.h
class CD3DWindow
{
public:
CD3DWindow();
~CD3DWindow();
LPDIRECT3D9 pD3D;
HRESULT PreInitD3D();
HWND hWnd;
bool killed;
VOID KillD3DWindow();
};
init3D.cpp
CD3DWindow::CD3DWindow()
{
pD3D=NULL;
}
CD3DWindow::~CD3DWindow()
{
if (!killed) KillD3DWindow();
}
HRESULT CD3DWindow::PreInitD3D()
{
pD3D = Direct3DCreate9( D3D_SDK_VERSION ); // Here it reports a problem
if( pD3D == NULL ) return E_FAIL;
// Other not related code
VOID CD3DWindow::KillD3DWindow()
{
if (killed) return;
diwrap::input.UnCreate();
if (hWnd) DestroyWindow(hWnd);
UnregisterClass( "D3D Window", wc.hInstance );
killed = true;
}
Inside main app .h
CD3DWindow *d3dWin;
Inside main app .cpp
d3dWin = new CD3DWindow;
d3dWin->PreInitD3D();
And here is the error report:
Error: UNINITIALIZED READ: reading register ebx
#0:00:02.969 in thread 4092
0x7c912a1f <ntdll.dll+0x12a1f> ntdll.dll!RtlUnicodeToMultiByteN
0x7e42d4c4 <USER32.dll+0x1d4c4> USER32.dll!WCSToMBEx
0x7e428b79 <USER32.dll+0x18b79> USER32.dll!EnumDisplayDevicesA
0x4fdfc8c7 <d3d9.dll+0x2c8c7> d3d9.dll!DebugSetLevel
0x4fdfa701 <d3d9.dll+0x2a701> d3d9.dll!D3DPERF_GetStatus
0x4fdfafad <d3d9.dll+0x2afad> d3d9.dll!Direct3DCreate9
0x00644c59 <Temp.exe+0x244c59> Temp.exe!CD3DWindow::PreInitD3D
c:\_work\Temp\initd3d.cpp:32
Edit: Your stack trace is very, very strange- inside the USER32.dll? That's part of Windows.
What I might suggest is that you're linking the multi-byte Direct3D against the Unicode D3D libraries, or something like that. You shouldn't be able to cause Windows functions to trigger an error.
Your Memory Validator application is reporting false positives to you. I would ignore this error and move on.
There is no copy constructor in your class CD3DWindow. This might not be the cause, but it is the very first thing that comes to mind.
If, by any chance, anywhere in your code a temporary copy is made of a CD3DWindow instance, the destructor of that copy will destroy the window handle. Afterwards, your original will try to use that same, now invalid, handle.
The same holds for the assignment operator.
This might even work, if the memory is not overwritten yet, for some time. Then suddenly, the memory is reused and your code crashes.
So start by adding this to your class:
private:
CD3DWindow(const CD3DWindow&); // left unimplemented intentionally
CD3DWindow& operator=(const CD3DWindow&); // left unimplemented intentionally
If the compiler complains, check the code it refers to.
Update: Of course, this problem might apply to all your other classes. Please read up on the "Rule of Three".