I'm trying to put interface pointers to different types of shaders in a vector like this:
std::vector<ID3D11DeviceChild*> shaders;
ID3D11VertexShader* VS;
// ... instantiate and init VS
shaders.push_back(static_cast<ID3D11DeviceChild*>(VS));
// and when VS is needed again:
ID3D11VertexShader* VS = static_cast<ID3D11VertexShader*>(shaders[i]);
// use VS here
My question is whether this method for type casting COM interfaces is safe. I know it would work for normal polymorphic class hierarchies, but I'm not sure about COM.
First, I'd suggest storing smart pointers instead of raw owning pointers inside an STL container like std::vector, e.g.
std::vector<CComPtr<ID3D11DeviceChild>> shaders;
Using raw owning pointers inside STL containers is a source of leaks, potential bugs and exception unsafe code (observing raw pointers are fine, though).
To downcast from ID3D11DeviceChild* to ID3D11VertexShader*, consider using QueryInterface() (again, using ATL smart pointers like CComPtr simplifies the code):
CComPtr<ID3D11VertexShader> spVertexShader;
HRESULT hr = (shaders[i])->QueryInterface(IID_PPV_ARGS(&spVertexShader));
if (FAILED(hr))
...
PS
Unless I'm missing something, since ID3D11VertexShader is a derived class of ID3D11DeviceChild, you don't need the static_cast here:
shaders.push_back(static_cast<ID3D11DeviceChild*>(VS));
This should be fine:
shaders.push_back(VS);
Note on CAdapt
Note that you may need to use CAdapt with std::vector:
std::vector<CAdapt<CComPtr<ID3D11DeviceChild>>> shaders;
A conformant C++11 STL implementation should not require CAdapt, but I think it's necessary at least with VS2008 and VS2010.
I'm not sure about more modern versions of Visual Studio, but it seems they fixed that, e.g.:
you may want to read the paragraph titled "Resistance to overloaded address-of operators" in this Visual C++ blog post.
ID3D11VertexShader inherits from ID3D11DeviceChild so you don't even need to use static_cast<ID3D11DeviceChild*> to push them to vector. The safer way to downcast vector elements to shader is to use QueryInterface:
CComPtr<ID3D11VertexShader> vs;
if (S_OK == shaders[i]->QueryInterface(IID_ID3D11VertexShader,
reinterpret_cast<void**>(&vs)))
{
// Use vs here
}
It is safe for as long as you're absolutely sure the vector only contains ID3D11VertexShader, in which case you should just use it instead of ID3D11DeviceChild.
If you intend the vector to contain a mix of interface pointers, each with the common ancestor ID3D11DeviceChild, you're better off relying on QueryInterface, both for storing into and retrieving from the vector.
Remember, correct code is better than fast code, at least to begin with.
When you profile, if, and only if, you find out that QI is a bottleneck, then you should do something about it, but I recommend you use a vector of structs which has a pointer to a ID3D11DeviceChild and an interface identifier (IID) so you can inspect at runtime which kind of interface pointer you stored:
struct DeviceChildPtr {
ID3D11DeviceChild *ptr;
REFIID riid;
};
std::vector<DeviceChildPtr> shaders;
// ... instantiate, initialize ...
DeviceChildPtr shader;
shader.ptr = static_cast<ID3D11DeviceChild*>(VS);
shader.iid = IID_ID3D11VertexShader;
shaders.push_back(static_cast<ID3D11DeviceChild*>(shader));
// ...
DeviceChildPtr shader = shaders[i];
// If you only ever use global IIDs, you may replace IsEqualIID with ==
// This is like a half-baked QueryInterface that only checks for a specific IID
if (IsEqualIID(shader.riid, IID_ID3D11VertexShader) {
ID3D11VertexShader* VS = static_cast<ID3D11VertexShader*>(shader.ptr);
// ... use ...
}
If you ever go through this path, remember to comment why (performance?) and how (casting, safety through runtime interface type check) you're doing it this way instead of using QueryInterface.
My guess is, since internally DX itself will most likely use QueryInterface, you shouldn't find a bottleneck here.
Related
The most satisfying part of writing a DIY memory manager is structuring it so you can forget about [delete] (e.g. by bundling everything into a singly allocated/deallocated buffer).
The way DirectX handles object creation means that you can't simply cast void memory into the types you want to make (can you?) and you have to rely on COM (+ remembering to [Release] local memory in every destructor) instead. Is there any way to subvert this and convince DirectX to use my pointers?
Instead of:
ID3D12Thing* thng = DirectX::CreateThing();
...
thng->Release();
thng = nullptr;
I want:
ID3D12Thing* thng = DirectX::CreateThingAt(Allocator->AlignedAlloc(sizeof(ID3D12Thing));
...
[memory emptied during shutdown]
Edit: This answer has been superseded by Chuck Walbourn's parallel answer.
While my answer is not completely wrong, after some investigation I'm pretty sure Chuck Walbourn's suggestion to use Microsoft::WRL::ComPtr is the better choice (Please see also comment section under C.B.'s answer for reasons). /Edit
To my knowledge it is not possible to plant external memory on Direct X structures, since they are all created by Direct X itself.
Nevertheless, if the main goal is maintenance and safety, it is possible to define a std::unique_ptr with a custom deleter which does the job of releasing.
struct DxDeleter {
void operator() (IUnknown* _moribund) { if(_moribund) _moribund->Release(); }
};
typedef std::unique_ptr<ID3D11Buffer,DxDeleter> dx_buffer_ptr;
typedef std::unique_ptr<ID3D11ShaderResourceView,DxDeleter> dx_resource_ptr;
typedef std::unique_ptr<ID3D11UnorderedAccessView,DxDeleter> dx_access_ptr;
...
The pointers then are simply assigned with e.g. myUniqueDxBufferPtr.reset( myRawBufferPtr ) or similar.
This has the high benefit, that releases don't need to be tracked. It is a good way not only for Direct X, but for all kinds of external libraries, which need allocation and deallocation (for example, I use the same technique also for Freeimage and ffmpeg).
It is also possible to define std::shared_ptrs for resources, which are shared by multiple items (e.g. you could keep your device alive as long as any buffers exist). But this is to handle with care - in opposite of std::unique_ptr, std::shared_ptrs don't have the deleter as a template parameter, but as a ctor parameter - which makes it terribly easy to erroneously assign something with a missing deleter (leaks).
void g_dxDelete( IUnknown* _moribund ) {
if( _moribund )
_moribund->Release();
}
typedef std::shared_ptr<ID3D11Device> dx_device_shared;
inline dx_device_shared assignDevice( ID3D11Device* _device ) {
return std::move( dx_device_shared( _device, g_dxDelete ) );
}
In that case you'd have to always be sure to assign the created device with dx_device_shared myDevice = assignDevice(myRawDevicePtr), but NEVER with dx_device_shared myDevice = myRawDevicePtr.
TL;DR: Use a smart-pointer like ComPtr.
I'm a big fan of std::unique_ptr and std::shared_ptr, but neither of them really correctly handle COM objects such as Direct3D interfaces which have their own built-in reference counts. A better choice is to use WRL class Microsoft::WRL::ComPtr or the C++/WinRT class winrt::com_ptr.
Some older coders might suggest the old ATL CComPtr, but the more modern Microsoft::WRL::ComPtr is a better choice.
Microsoft recently released a new library (WIL) for modern C++. It includes a new com pointer type:
wil::com_ptr<ID3D12Thing> thng{DirectX::CreateThing())};
I am trying to write a simple game using C++ and SDL. My question is, what is the best practice to store class member variables.
MyObject obj;
MyObject* obj;
I read a lot about eliminating pointers as much as possible in similar questions, but I remember that few years back in some books I read they used it a lot (for all non trivial objects) . Another thing is that SDL returns pointers in many of its functions and therefor I would have to use "*" a lot when working with SDL objects.
Also am I right when I think the only way to initialize the first one using other than default constructor is through initializer list?
Generally, using value members is preferred over pointer members. However, there are some exceptions, e.g. (this list is probably incomplete and only contains reason I could come up with immediately):
When the members are huge (use sizeof(MyObject) to find out), the difference often doesn't matter for the access and stack size may be a concern.
When the objects come from another source, e.g., when there are factory function creating pointers, there is often no alternative to store the objects.
If the dynamic type of the object isn't known, using a pointer is generally the only alternative. However, this shouldn't be as common as it often is.
When there are more complicated relations than direct owner, e.g., if an object is shared between different objects, using a pointer is the most reasonable approach.
In all of these case you wouldn't use a pointer directly but rather a suitable smart pointer. For example, for 1. you might want to use a std::unique_ptr<MyObject> and for 4. a std::shared_ptr<MyObject> is the best alternative. For 2. you might need to use one of these smart pointer templates combined with a suitable deleter function to deal with the appropriate clean-up (e.g. for a FILE* obtained from fopen() you'd use fclose() as a deleter function; of course, this is a made up example as in C++ you would use I/O streams anyway).
In general, I normally initialize my objects entirely in the member initializer list, independent on how the members are represented exactly. However, yes, if you member objects require constructor arguments, these need to be passed from a member initializer list.
First I would like to say that I completely agree with Dietmar Kühl and Mats Petersson answer. However, you have also to take on account that SDL is a pure C library where the majority of the API functions expect C pointers of structs that can own big chunks of data. So you should not allocate them on stack (you shoud use new operator to allocate them on the heap). Furthermore, because C language does not contain smart pointers, you need to use std::unique_ptr::get() to recover the C pointer that std::unique_ptr owns before sending it to SDL API functions. This can be quite dangerous because you have to make sure that the std::unique_ptr does not get out of scope while SDL is using the C pointer (similar problem with std::share_ptr). Otherwise you will get seg fault because std::unique_ptr will delete the C pointer while SDL is using it.
Whenever you need to call pure C libraries inside a C++ program, I recommend the use of RAII. The main idea is that you create a small wrapper class that owns the C pointer and also calls the SDL API functions for you. Then you use the class destructor to delete all your C pointers.
Example:
class SDLAudioWrap {
public:
SDLAudioWrap() { // constructor
// allocate SDL_AudioSpec
}
~SDLAudioWrap() { // destructor
// free SDL_AudioSpec
}
// here you wrap all SDL API functions that involve
// SDL_AudioSpec and that you will use in your program
// It is quite simple
void SDL_do_some_stuff() {
SDL_do_some_stuff(ptr); // original C function
// SDL_do_some_stuff(SDL_AudioSpec* ptr)
}
private:
SDL_AudioSpec* ptr;
}
Now your program is exception safe and you don't have the possible issue of having smart pointers deleting your C pointer while SDL is using it.
UPDATE 1: I forget to mention that because SDL is a C library, you will need a custom deleter class in order to proper manage their C structs using smart pointers.
Concrete example: GSL GNU scientific library. Integration routine requires the allocation of a struct called "gsl_integration_workspace". In this case, you can use the following code to ensure that your code is exception safe
auto deleter= [](gsl_integration_workspace* ptr) {
gsl_integration_workspace_free(ptr);
};
std::unique_ptr<gsl_integration_workspace, decltype(deleter)> ptr4 (
gsl_integration_workspace_alloc (2000), deleter);
Another reason why I prefer wrapper classes
In case of initialization, it depends on what the options are, but yes, a common way is to use an initializer list.
The "don't use pointers unless you have to" is good advice in general. Of course, there are times when you have to - for example when an object is being returned by an API!
Also, using new will waste quite a bit of memory and CPU-time if MyObject is small. Each object created with new has an overhead of around 16-48 bytes in a typical modern OS, so if your object is only a couple of simple types, then you may well have more overhead than actual storage. In a largeer application, this can easily add up to a huge amount. And of course, a call to new or delete will most likely take some hundreds or thousands of cycles (above and beyond the time used in the constructor). So, you end up with code that runs slower and takes more memory - and of course, there's always some risk that you mess up and have memory leaks, causing your program to potentially crash due to out of memory, when it's not REALLY out of memory.
And as that famous "Murphy's law states", these things just have to happen at the worst possible and most annoying times - when you have just done some really good work, or when you've just succeeded at a level in a game, or something. So avoiding those risks whenever possible is definitely a good idea.
Well, creating the object is a lot better than using pointers because it's less error prone. Your code doesn't describe it well.
MyObj* foo;
foo = new MyObj;
foo->CanDoStuff(stuff);
//Later when foo is not needed
delete foo;
The other way is
MyObj foo;
foo.CanDoStuff(stuff);
less memory management but really it's up to you.
As the previous answers claimed the "don't use pointers unless you have to" is a good advise for general programming but then there are many issues that could finally make you select the pointers choice. Furthermore, in you initial question you are not considering the option of using references. So you can face three types of variable members in a class:
MyObject obj;
MyObject* obj;
MyObject& obj;
I use to always consider the reference option rather than the pointer one because you don't need to take care about if the pointer is NULL or not.
Also, as Dietmar Kühl pointed, a good reason for selecting pointers is:
If the dynamic type of the object isn't known, using a pointer is
generally the only alternative. However, this shouldn't be as common
as it often is.
I think this point is of particular importance when you are working on a big project. If you have many own classes, arranged in many source files and you use them in many parts of your code you will come up with long compilation times. If you use normal class instances (instead of pointers or references) a simple change in one of the header file of your classes will infer in the recompilation of all the classes that include this modified class. One possible solution for this issue is to use the concept of Forward declaration, which make use of pointers or references (you can find more info here).
Windows handles are sometimes annoying to remember to clean up after (doing GDI with created pens and brushes is a great example). An RAII solution is great, but is it really that great making one full (Rule of Five) RAII class for each different type of handle? Of course not! The best I can see would be one full generic RAII class with other classes just defining what to do when the handle should be cleaned up, as well as other handle-specific aspects.
For example, a very simple module class could be defined like this (just an example):
struct Module {
Module() : handle_{nullptr} {}
Module(HMODULE hm) : handle_{hm, [](HMODULE h){FreeLibrary(h);}} {}
operator HMODULE() const {return handle_.get();}
private:
Handle<HMODULE> handle_;
};
That's all fine and dandy, and no destructor or anything is needed. Of course, though, being able to write the Handle class to not need a destructor or anything as well would be nice, too. Why not use existing RAII techniques? One idea would be to use a smart pointer to a void, but that won't work. Here's how the handles are actually declared under normal circumstances:
#define DECLARE_HANDLE(n) typedef struct n##__{int i;}*n
DECLARE_HANDLE(HACCEL);
DECLARE_HANDLE(HBITMAP);
DECLARE_HANDLE(HBRUSH);
...
It actually differentiates between handle types, which is good, but it makes using a smart pointer to void impossible. What if, instead, since handles are, by definitions, pointers, the type could be extracted?
My question is whether the following is a safe assumption to make. It uses a handle to a desktop, which must be closed. Barring the differences between shared and unique pointers (e.g., FreeLibrary has its own reference counting semantics), is assuming the handle is a pointer and making a smart pointer to whatever it's pointing to okay, or should I not use smart pointers and make Handle implement the RAII aspects itself?
#include <memory>
#include <type_traits>
#include <utility>
#include <windows.h>
int main() {
using underlying_type = std::common_type<decltype(*std::declval<HDESK>())>::type;
std::shared_ptr<underlying_type> ptr{nullptr, [](HDESK desk){CloseDesktop(desk);}};
}
I believe all Windows pointers are technically pointers to internal objects inside the Windows kernel part of the system (or sometimes, possibly, to user-side objects allocated by the kernel code, or some variation on that theme).
I'm far from convinced that you should TREAT them as pointers tho'. They are only pointers in a purely technical perspective. They are no more "pointers" than C style "FILE *" is a pointer. I don't think you would suggest the use of shared_ptr<FILE*> to deal with closing files later on.
Wrapping a handle into something that cleans it up later is by all means a good idea, but I don't think using smart pointer solutions is the right solution. Using a templated system which knows how to close the handle would be the ideal.
I suppose you also would need to deal with "I want to pass this handle from here to somewhere else" in some good way that works for all involved - e.g. you have a function that fetches resources in some way, and it returns handles to those resources - do you return an already wrapped object, and if so, how does the copy work?
What if you need to save a copy of a handle before using another one (e.g. save current pen, then set a custom one, then restore)?
One approach you could take is to use a template class:
template<typename H, BOOL(WINAPI *Releaser)(H)>
class Handle
{
private:
H m_handle;
public:
Handle(H handle) : m_handle(handle) { }
~Handle() { (*Releaser)(m_handle); }
};
typedef Handle<HANDLE,&::CloseHandle> RAIIHANDLE;
typedef Handle<HMODULE,&::FreeLibrary> RAIIHMODULE;
typedef Handle<HDESK,&::CloseDesktop> RAIIHDESKTOP;
If there is a HANDLE which isn't released by a function of type BOOL(WINAPI)(HANDLE), then you may have issues with this. If the releasing functions only differ by return type though, you could add that as a template parameter and still use this solution.
Technically, this ought to work perfectly well under all present versions of Windows, and it is hard to find a real reason against doing it (it is actually a very clever use of existing standard library functionality!), but I still don't like the idea because:
Handles are pointers, and Handles are not pointers. Handles are opaque types, and one should treat them as such for compatibility. Handles are pointers, and it is unlikely that handles will ever be something different, but it is possible that this will change. Also, handles may or may not have values that are valid pointer values, and they may or may not have different values under 32bit and 64bit (say INVALID_HANDLE_VALUE), or other side effects or behaviours that you maybe don't foresee now. Assuming that a handle has certain given properties may work fine for decades, but it may (in theory) mysteriously fail in some condition that you didn't think about. Admittedly, it is very unlikely to happen, but still it isn't 100% clean.
Using a smart pointer in this way doesn't follow the principle of least astonishment. Because, hey, handles aren't pointers. Having RAII built into a class that is named with an intuitive name ("Handle", "AutoHandle") will not cause anyone to raise an eyebrow.
I believe that both unique_ptr and shared_ptr allow you to provide custom deleter. Which I believe is just what you need to correctly manage lifetime of handles.
I'm writing a program in Windows COM in C++ and I'm using CComPtr for smart pointers.
The question I can't find answer to is - Can I use CComPtr inside of a std::map.
I have the following code fragment (simplified):
std::map<int, CComPtr<IErrorInfo> > ErrorMap;
I wish to maintain this mapping between ints and IErrorInfo error infos.
However I'm not sure if I can do the following:
CComPtr<IErrorInfo> result;
GetErrorInfo(0, &pErrInfo);
ErrorMap.insert(std::make_pair(0, result));
I'm concerned about ownership of the result smart pointer and if it will get released correctly when ErrorMap gets destroyed?
You need to wrap your CComPtr in CAdapt for this to work.
The adapter class CAdapt is useful because many container classes
(such as the STL container classes) expect to be able to obtain the
addresses of their contained objects using the address-of operator.
The redefinition of the address-of operator can confound this
requirement, typically causing compilation errors and preventing the
use of the unadapted type with that container. CAdapt provides a way
around those problems.
I'm trying to leave MFC, how can I replace CPtrArray ?
maybe I can typedef it to something alike vector<void *>
What is better way to save full functional of this class ?
thank you.
You should not have been using CPtrArray in the first place. It is a dangerous old class from the dark days before Visual C++ supported templates and can only be used with enormous caution. Its problem is that it stores pointers (any pointer!) as void* and that means that when you get the pointer back out of the array you have no type information whatsoever. If your code relies heavily on this you have been at risk of misusing objects and of serious memory leaks (e.g. failing to call destructors).
boost::ptr_array is not a direct replacement for CPtrArray, it is a properly templated type-sensitive class: its nearest MFC equivalent would be CArray<T>. The fact that it uses void* to handle the pointers is (essentially) an implementation detail, and not the same at all as using vector<void*> directly.
(If you are aware of all the issues with CPtrArray then I apologise for preaching to the choir, but I thought any question about CPtrArray needed a warning note attached.)
No need to write it yourself, you can use boost::ptr_array instead. It uses an underlying std::vector<void*> to store the pointers.