Why does CDC::SelectObject(CFont*) accept a CFont object vs. a pointer? - c++

CPaintDC dc(this);
CFont font;
dc.SelectObject(font); // why does this build?
The function CDC::SelectObject takes a pointer of type CFont but why does this build with providing an object? I came across this issue that the above code is unpredictable and can crash sometimes but not always.

The code in question is valid, sort of. It compiles due to a combination of two things:
The CFont::operator HFONT().
An undocumented CDC::SelectObject overload taking an HGDIOBJ handle.
When the compiler tries to match an overload for dc.SelectObject(font), none of them match. So next it tries the user-defined conversion operator (operator HFONT()) that returns an HFONT. That matches the undocumented overload taking an HGDIOBJ (both HGDIOBJ and HFONT are typedef'd as void*).
The code posted in the question is almost correct, too, with 2 exceptions:
The font object is destroyed while still being selected into a device context. While this causes a double-delete bug (the font object is owned by the CFont instance and the device context), the call to DeleteFont gracefully fails when passed an invalid handle.
The font object previously selected into the device context is lost, and thereby leaked.
Neither issue causes unpredictable behavior or intermittent crashes. As explained in your answer, the real code, however, looks like this:
CFont* pOldFont = (CFont*) dc.SelectObject(font);
That is a bug that exhibits undefined behavior. dc.SelectObject(font) returns an HGDIOBJ (typedef'd as void*), which is subsequently cast to an unrelated type (CFont*). While storing the font previously selected into the device context to later restore it is correct, the code is not. An implementation that honors ownership could be:
CPaintDC dc(this);
CFont font;
CFont oldFont;
// Transfer ownership of font to the DC, and the previously selected font into oldFont
oldFont.Attach(dc.SelectObject(font.Detach()));
// Use dc
// Transfer ownership back
font.Attach(dc.SelectObject(oldFont.Detach()));
// oldFont goes out of scope; this a no-op since it no longer owns any resources
// font goes out of scope, releasing all resources owned by it
// dc goes out of scope, releasing all resources owned by objects selected into it
If you are willing to temporarily sacrifice strict ownership semantics, you can make your life easier by using the more standard implementation:
CPaintDC dc(this);
CFont font;
CFont* pOldFont = dc.SelectObject(&font);
// Use dc
dc.SelectObject(pOldFont);
This is safe, even if you exit early, without restoring the device context. It would still lead to a double-delete on the font object owned by both the CFont instance and the device context (which is handled gracefully by the API). It doesn't exhibit a font leak, though, because things are more complicated than it seems: There is another invisible owner involved here, a map controlled by MFC that stores temporary objects (like those returned from CGdiObject::FromHandle, which SelectObject(CFont*) calls). The temporary objects are cleaned up as part of MFC's idle time processing.

I agree with answer by IInspectable and here is my own proof of concept how this works:
#include "stdafx.h"
#include <iostream>
class A {
int a_int = 6;
char* a_carp = "A derived";
public:
operator int() { return a_int; }
operator char*() { return a_carp; }
};
class B : public A {
float b_float = 5.7;
char* b_carp = "B Derived";
public:
operator float() { return b_float; }
operator char*() { return b_carp; }
};
void Print(char * text)
{
std::cout << text << std::endl;
}
int main() {
B b_obj;
// long a = b_obj;
char* c_p = b_obj;
Print(b_obj);
return 0;
}
The above code builds and the output is "B Derived".
How does it works?
When we use an object in place of a different type, the object looks for appropriate conversion operator. If it finds it, it applies it and converts that for you.
In this case, that operator was HFONT(). It is important to note the actual name of the operator doesn't matter, its the return type/signature that matters. So when it finds a match (correct signature), it calls it.
Why unpredictable behavior?
Let me clear that as well since I mention that in OP. The code I posted was related to build issue but the actual code was this:
CFont* pOldFont = (CFont*) dc.SelectObject(font);
And the forced typecasting (CFont*) was the problem. If we pass HGDIOBJ to SelectObject(), it returns HGDIOBJ but it was forced typecasted to CFont * and that was the problem so there is nothing else wrong with using conversion operators.

Related

Is there a _safe_ way to send a string via the PostMessage?

I want to raise this question one more time. I wrote a comment on the accepted answer already, but, it seems, the answered person is inactive on the SO. So, I copy my comment-question here.
In the accepted answer on the referred question, there is a potential risk of the memory leakage. For example, the PostMessage can be resulted with error because of the messages queue is full. Or, the target window may be already destroyed (so, the delete operator will not be called).
As a summary, there is no a strong corresponding between the posting and the receiving of the Windows message. But, on the other hand, there are not so many options how to pass a pointer (to a string, for example) with the Windows message. I see only two: to use objects allocated in the heap or declared as the global variables. The former one has the difficulty which is described here. The latter one is deprived of the specified disadvantage, but there is need to allocate some memory which may be used rarely.
So, I have these questions:
May someone suggest a way, how we can be safe against the memory leakage in the case of using of the heap memory for "attaching" something to the Windows message?
Is there some another option how we can reach the goal (send a string, for example, within the Windows message via the PostMessage system call)?
use std::wstringstream.
look for EM_STREAMOUT.
wchar_t remmi[1250];
//make stuff
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
hc=CreateWindowEx(WS_EX_NOPARENTNOTIFY, MSFTEDIT_CLASS,remmi,
ES_MULTILINE|ES_AUTOVSCROLL| WS_VISIBLE | WS_CHILD
|WS_TABSTOP|WS_VSCROLL,
1, 350, 450, 201,
this->m_hWnd, NULL, h, NULL);
return 0;
}
//middleware
DWORD CALLBACK E(DWORD_PTR dw, LPBYTE pb, LONG cb, LONG *pcb)
{
std::wstringstream *fr = (std::wstringstream *)dw;
fr->write((wchar_t *)pb, int(cb/2));
*pcb = cb;
return 0;
}
//final
void CMainFrame::tr()
{
std::wstringstream fr;
EDITSTREAM es = {};
es.dwCookie = (DWORD_PTR) &fr;
es.pfnCallback = E;
::SendMessage(hc, EM_STREAMOUT, SF_TEXT|SF_UNICODE, (LPARAM)&es);
ZeroMemory(remmi,1218*2);
fr.read(remmi,747);
}

Which are the safe way to send CString through PostMessage from thread

What is the safe / best way to send a CString through PostMessage, from a thread ?
To create CString on heap and clean up when the receiver get this CString ?
Solution 1: In thread:
CString* pError = new CString(_T("Unknown error"));
::PostMessage(...(LPARAM)pError);
and in main thread, somewhere in GUI:
CString* pError = (CString*)lParam;
GetDocument()->DoSomething(*pError);
delete pError;
Solution 2:
Or, to keep CString object as member variable inside of CThread class ?
class CPlanThread : public CThread [: public CObject]
{
public:
DECLARE_DYNAMIC(CPlanThread)
...
protected:
CString* m_pMessage;
};
and
CPlanThread::CPlanThread()
:m_pMessage(NULL)
{
m_pMessage = new CString(_T(""));
}
CPlanThread::~CPlanThread()
{
if(NULL != m_pMessage)
delete m_pMessage;
}
and somewhere in thread:
::PostMessage(m_hWndMain, WMU_NOTIFYTHREAD, 0, (LPARAM)m_pMessage);
and in main thread, somewhere in GUI:
CString* pError = (CString*)lParam;
GetDocument()->DoSomething(*pError);
Both of the above solutions are safe ? Kindly thank you for any explanation.
The first option is the safer alternative.* The only reason, why this could result in a resource leak is, if the call to ::PostMessage fails, and you aren't cleaning up in the sender. Note, that this does not lead to a crash.
The second alternative creates a race condition, since you are holding on to a pointer, whose ownership you meant to transfer. If the GUI thread tries access the string after the thread objects has been destroyed, you are accessing random memory. This can lead to an immediate crash, if you are lucky.
Depending on your specific use case, you might want to consider using a third alternative: Using a CString object with automatic storage duration and thread synchronization through message-sending, e.g.:
CStringW err( L"Unknown error" );
::SendMessage( ..., (LPARAM)&err );
The receiving thread can use the string object for as long as it is in its message handler, and the sender will automatically clean up the resource.
* That is assuming, that both threads are implemented in the same module. Make sure to read Potential Errors Passing CRT Objects Across DLL Boundaries in case they aren't.
I would always prefer to store things in a member variable (which means there is an object responsible for cleaning them up). However, see an important caveat below. I would also prefer to hold a CString by value, rather than by pointer. Storing the pointer just makes another bit of memory you've got to manage. So:
class CPlanThread : public CThread [: public CObject]
{
public:
DECLARE_DYNAMIC(CPlanThread)
...
protected:
CString m_Message;
};
and
CPlanThread::CPlanThread()
:m_Message(L"")
{
}
CPlanThread::~CPlanThread()
{
}
and then
::PostMessage(m_hWndMain, WMU_NOTIFYTHREAD, 0, (LPARAM)&m_Message);
Note that this approach means you don't need to do anything in the destructor, and the constructor can initialize the variable (actually, you should have used initialization on the pointer).
I have removed the _T() macro. It's a really bad idea, unless you actually build versions of the software with both types of character (which doubles your testing effort for no benefit). Just get used to writing your literals with a leading 'L'.
Final comment, there is no point testing if a pointer is nullptr before deleting it - delete does that check anyway.
Important Caveat
This approach means you need to make sure that the CPlanThread object exists until after the message is processed - but you had to do that with the pointer member anyway.
If you can't ensure that lifetime, but you can just use string literals, then post a const wchar_t* and you don't have to manage lifetimes.
If you can't ensure the lifetime is long enough, and you can't just use literals, then you will have to use the new/delete approach.

C++ access violation when calling instance method

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

heap corruption when deconstructing sf::Image array

so I'm trying to make a fade transition animation for an sf::Image in SFML, and I'm have a small problem.
When I don't comment out the function called below, I get an error at the end of main() when the images are being deconstructed saying
"Windows has triggered a breakpoint. This may be due to a corruption
of the heap."
The line this happens on contains the code GLCheck(glDeleteTextures(1, &Texture));
Why would this be happening, and why only when CreateTransition() is run?
One more note: when I comment out aray[I] = aray[0] the break doesn't occur.
I posted the function below.
void CreateTransition(sf::Image& start, sf::Image animationArray[numbImgs]){
animationArray[0] = start;
void threadFunc(void* imgArray);
sf::Thread thread(threadFunc, reinterpret_cast<void*>(animationArray));
thread.Launch();
thread.Wait(); // comment this out once I get the code working
}
void threadFunc(void* ptr){
sf::Image* aray = reinterpret_cast<sf::Image*> (ptr);
sf::Color filter(0, 0, 0, 5);
for(int I= 1; I< numbImgs; I++){
//aray[I].Copy(aray[0], 0, 0, sf::IntRect(0, 0, 0, 0), true);
aray[I] = aray[0]; // error doesn't occur when commented out
RecolorImage(aray[I], filter);
}
}
Image& Image::operator =(const Image& Other)
{
Image Temp(Other);
std::swap(myWidth, Temp.myWidth);
std::swap(myHeight, Temp.myHeight);
std::swap(myTextureWidth, Temp.myTextureWidth);
std::swap(myTextureHeight, Temp.myTextureHeight);
std::swap(myTexture, Temp.myTexture);
std::swap(myIsSmooth, Temp.myIsSmooth);
std::swap(myNeedArrayUpdate, Temp.myNeedArrayUpdate);
std::swap(myNeedTextureUpdate, Temp.myNeedTextureUpdate);
myPixels.swap(Temp.myPixels);
return *this;
}
A few things which might help you narrow down the cause:
A heap corruption rarely occurs at the point when the program crashes which makes them hard to track down. It may be related to the object at the crash point or it may have been another object/code that corrupted it.
In CreateTransition() you pass the animationArray[] by value but you then pass it into a thread procedure. The lifetime of animationArray[] ends when you return from CreateTransition() which means if the thread procedure runs after this point its void* ptr parameter will not point to a valid object. You do have a thread.Wait() in the current code but also a comment about removing it. Either pass animationArray[] by reference unless there is a specific reason not to, or create a temporary copy for the thread procedure to ensure it operates on valid objects.
Consider using a std::vector<sf::Image> instead of an array.
Make sure you understand and implement the Rule of Three for sf::image and any dependent classes (like MyPixels). Not doing this can result in double-frees, leaked memory, and heap corruption like you are seeing.
If all else fails try to duplicate the issue in a temporary test project and reduce it to the smallest amount of code possible. Eliminate members of sf::image one at a time until the problem goes away. Similarly, delete lines from CreateTransition() and other lines from the thread procedure. You'll either end up with a few very specific lines that trigger the issue or an empty project.

Uninitialized read problem

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".