Search code examples
c++comdirectxsmart-pointersdirectx-10

NULL pointer, thought it seems to be initialized


I get

Debug assertion failed.
p!=0

and it points to:

    _NoAddRefReleaseOnCComPtr<T>* operator->() const throw()
    {
        ATLASSERT(p!=NULL);
        return (_NoAddRefReleaseOnCComPtr<T>*)p;
    }

in 'atlcomcli.h'

From what I understand it means I have forgot to initialize a pointer somewhere, but all of them seem to be initialized.

When I use normal pointers instead of 'CComPtr', it throws 'Access Violation Reading Location' at 'font->DrawTextA' in 'D3DFont::Draw' in D3DFont.cpp

//D3DFont.h:
#include <D3DX10.h>
#include <atlbase.h>
#include <string>

class D3DFont
{
public:
    D3DFont(void);
    ~D3DFont(void);

    bool Create(ID3D10Device *device, std::string name, int width,
        int height, int weight, int mipLevels, bool italic, BYTE charset,
        BYTE quality, BYTE pitchAndFamily);
    void Draw(LPD3DX10SPRITE sprite, std::string text, int charCount,
        LPRECT rect, UINT format, D3DXCOLOR color);

private:
    CComPtr<ID3DX10Font> font;
};

//D3DFont.cpp:
#include "D3DFont.h"

D3DFont::D3DFont(void){} 
D3DFont::~D3DFont(void){}

bool D3DFont::Create( ID3D10Device *device, std::string name,
    int width, int height, int weight, int mipLevels, bool italic,
    BYTE charset, BYTE quality, BYTE pitchAndFamily )
{
    D3DX10_FONT_DESC fd;
    ZeroMemory(&fd, sizeof(D3DX10_FONT_DESC));

    fd.Height = height;
    fd.Width = width;
    fd.Weight = weight;
    fd.MipLevels = mipLevels;
    fd.Italic = italic;
    fd.CharSet = charset;
    fd.Quality = quality;
    fd.PitchAndFamily = pitchAndFamily;

    strcpy_s(fd.FaceName, name.c_str());

    // INITIALIZING FONT HERE
    D3DX10CreateFontIndirect(device, &fd, &font);

    return true;
}

void D3DFont::Draw( LPD3DX10SPRITE sprite, std::string text,
    int charCount, LPRECT rect, UINT format, D3DXCOLOR color )
{
    // ERROR HERE
    font->DrawTextA(sprite, text.c_str(), charCount, rect, format, color); 
}

And my use of above functions:

if( !font.Create(d3d.GetDevice(), "Impact", 0, 175, 0, 1, false,
    OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE) )
{
    MessageBox(0, "Could not create font.", "Error!", MB_OK | MB_ICONERROR);
}

// later on...

RECT r = {35, 50, 0, 0};
font.Draw(0, "Test", -1, &r, DT_NOCLIP, d3d.GetColorObj(1.0f, 1.0f, 0.0f, 1.0f));

What could I miss?


'D3DX10CreateFontIndirect' throws 0x8876086C Can't find what does it mean, but some google threads are related to d3dDevice, so I guess it must be related to it. Will update when I will have more info.


Solution

  • Calling the D3DX10CreateFontIndirect doesn't actually guarantee that your pointer will be initialized.

    Rule of thumb : ALWAYS check HRESULTs when using DirectX functions that initialize a pointer:

    HRESULT hr = D3DX10CreateFontIndirect(device, &fd, &font);
    
    if(FAILED(hr)){
        //Get the last error, display a message, etc.
        //Eventually propagate the error if the code can't continue 
        //with the font pointer uninitialized.
    }
    

    When your function returns E_FAIL, do not try to use the pointer afterward. There are great chances that the values of the parameters are simply incorrect (here, your device pointer might be null or your font description might be incorrect).