Archived

This topic is now archived and is closed to further replies.

AlbertoT

if ( FAILED (...)

Recommended Posts

Professional game programs are full of : if FAILED(lpD3DRM->CreateMesh...) goto generic_error; I never use if FAILED ... being a lazy amateur I do not care if my code FAIL , from time to time, but just as a matter of curiosity. Does it fail so often? If so, who is the guilty? The hardware, Windows, the third law of thermodinamics ? may be direct x? thanks and regards to all GameDev members

Share this post


Link to post
Share on other sites
quote:
Original post by AlbertoT
Professional game programs are full of :

if FAILED(lpD3DRM->CreateMesh...)
goto generic_error;


this is the standard way of checking for errors in COM world, to which DX belongs.
quote:

I never use if FAILED ... being a lazy amateur I do not care if my code FAIL , from time to time, but just as a matter of curiosity.


you better start checking for errors, because they are inevitable and error checking saves on debugging time.
quote:

Does it fail so often?


it depends on how sloppy you write your programs.
quote:

If so, who is the guilty?
The hardware, Windows, the third law of thermodinamics ? may be direct x?


i think it would be safe to say that in over 99% of the cases the programmer is, so add error checking to your programs.



---
Come to #directxdev IRC channel on AfterNET

Share this post


Link to post
Share on other sites
Ideally, it never fails at all. But when it does, it''s nice to know EXACTLY when that is. You say you''re lazy; I say you''re inexperienced. Once you''ve done a lot of debugging, you''ll appreciate how essential assiduous error checking is.

Share this post


Link to post
Share on other sites
Not so much as the API failing, but more, if you try to do something that something on the system does not support, or if the system is busy doing something else. For example, if you try to set a display adapter resolution that the adapter doesn''t support (i.e. 2048x1536x24bpp), which might exist on some high-end graphics cards) then you need to be able to tell whether or not that attempt fails in software, to properly compensate and notify the user that it''s not possible. Likewise, if you try to page flip on a device that has only a primary buffer, you would get a return value (not necessarily an error) indicating the action is not possible (or the screen update should be blitted rather than page-flipped).

As for whether or not testing with FAILED() is professional is a matter of personal opinion.



MatrixCubed
http://MatrixCubed.cjb.net

Share this post


Link to post
Share on other sites

Well, to add my two pence - even if you don''t really mind if FAILED is true, I can guess the users of your programs do Of course, if you don''t have any - it doesn''t matter! Using FAILED will **at the very least** enable you to present a message to the user explaining why all around them is about to come crashing down - apart from that, yep, its useful for debugging.

Share this post


Link to post
Share on other sites
If you don''t bother checking for errors and you''re actually getting anywhere in what your doing you''ll have a rude awakening when you want your stuff to run on other computers.

------------
- outRider -

Share this post


Link to post
Share on other sites
Two types of things which will return failure SCODEs/HRESULTs:

1. Things which could feasibly happen in a bug free app in the real world. For example DX device creation failing due to lack of memory.

2. Things which shouldn''t happen in a properly written, bug free app. In DX for example you have caps flags and ValidateDevice, so a SetRenderState for example should never fail because code earlier on should have prevented invalid values being passed.


For Type #1, we always use the FAILED() and SUCCEEDED() macros, and often also act on the actual code returned after it''s been trapped by one of those.

For Type #2, we use a macro which performs the test and a report in debug builds and compiles away to nothing in release builds:

#ifdef _DEBUG
#define TRYDX(fn) do { \
HRESULT __dbgHResult__ = fn; \
if (FAILED(__dbgHResult__)) { \
_dbgLogDirectXError( __FILE__, __LINE__, __dbgHResult__, #fn ); \
} \
} while(0);

#else
#define TRYDX(fn) (fn)
#endif


_dbgLogDirectXError is a global function only present in debug builds which produces a report including the line number and source file of where the error occured along with the actual line itself and a translation of the error code into English.
Usually this report is sent to the debug stream (OutputDebugString), but can be logged to a file or even cause an error box.


--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Share this post


Link to post
Share on other sites
quote:
Original post by S1CA
2. Things which shouldn''t happen in a properly written, bug free app. In DX for example you have caps flags and ValidateDevice, so a SetRenderState for example should never fail because code earlier on should have prevented invalid values being passed.


I used to check all dx return values, but gave up, and here''s my reason why. The docs state that retail runtime doesn''t perform parameter validation in many cases, so an error return from SetRenderState or similar or very unlikely (from the retail runtime). Therefore, checking for error returns is pointless. At the same time, with debug runtime I use ''break on error'' feature and there''s no need to add error handling because dx will break anyway, along wth something more meaningful than D3DERR_INVALIDCALL. I do check all functions that might fail in normal conditions, like Create... ones and Present.

Reasonable?

---
Come to #directxdev IRC channel on AfterNET

Share this post


Link to post
Share on other sites
quote:

I used to check all dx return values, but gave up, and here''s my reason why. The docs state that retail runtime doesn''t perform parameter validation in many cases, so an error return from SetRenderState or similar or very unlikely (from the retail runtime).



Yep it is entirely reasonable to not check calls which fall into category 2 of my original reply.

"Break on D3D error" is indeed a good way to trap those for D3D errors.


However, there isn''t a "break on error" for other DirectX components, plus its use implies you have a development environment and the full source code available.

When we''re testing stuff which is still in development, people within the company without the full source code or even dev environments will sometimes report problems. The function called by the macro will log to a file (when set to do so) so we get to the problem much quicker on any machine.

It''s much easier to install the debug DX runtime than it is to install dev tools and the codebase!


IMO you should do as much as possible at code level (asserts etc) to provide an early warning system - e.g. someone changes something wrongly - an assert pops up as soon as they test it - they can fix the issue immediately while they can still remember what they changed .

--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Share this post


Link to post
Share on other sites
quote:
Original post by S1CA
However, there isn''t a "break on error" for other DirectX components, plus its use implies you have a development environment and the full source code available.


Good point, thanks. I''ll consider asserting everything.

---
Come to #directxdev IRC channel on AfterNET

Share this post


Link to post
Share on other sites