views:

87

answers:

4

I'm using C++ in Visual Studio 2005 and I'm getting many warnings that read

potentially uninitialized local variable 'hr' used

Where hr is defined as

HRESULT hr;

What's the correct way to initialize HRESULT?

+2  A: 

I would use:

HRESULT hr = NOERROR;

You could also use

HRESULT hr = S_OK;

Both set it to 0.

Ferruccio
+3  A: 

Pick an error HRESULT value and use that, so HRESULT hr = E_UNEXPECTED or HRESULT hr = E_FAIL would be good choices I expect.

Len Holgate
I guess I'm more optimistic :-) but I like this approach. +1
Ferruccio
This tends to be more robust than S_OK. The reason is that there are more failure modes than success modes for most functions, and therefore more failure return paths. Yet the function is written to succeed, and most care is given to that return path. Thus it's very uncommon to forget the `hr = S_OK;` statement on the succesful return path, but missing `hr = E_FAIL` on a failure case happens all too often.
MSalters
I always find it safer to assume failure... And the text for `E_UNEXPECTED` is just SO good ;)
Len Holgate
+1  A: 

Depends on chat you want:

  • Fail by default ? Use E_FAIL
  • Success by default ? use S_OK
  • hr value is irrelevant if the subsequent code fails to initialize it ? Use E_UNEXPECTED
Samuel_xL
+3  A: 

Do not suppress the warnings by initializing the variables. The warnings are telling you that the code is Bad. Fix the code.

Some useful techniques:

  • Declare variables as close to first use as practically possible.
  • Translate error codes and HRESULTs to C++ exceptions.
  • Wrap API functions that you use repeatedly and that have particularly ungood design.

Translating from HRESULT to exception can be done very concisely and almost readably by using the ">> throwing pattern", like (although this example doesn't involve HRESULTs it shows that that pattern generalizes to handle most C style schemes) ...

std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
    Size const  nBytes      = wcstombs( 0, s, 0 );
    (nBytes >= 0)
        || throwX( "wcstombs failed to deduce buffer size" );

    Size const              bufSize     = nBytes + 1;
    std::vector< char >     buf( bufSize );

    // The count of bytes written does not include terminating nullbyte.
    wcstombs( &buf[0], s, bufSize )
        >> Accept< IsNonNegative >()
        || throwX( "wcstombs failed to convert string" );

    return (stream << &buf[0]);
}

The support definitions needed for this are not complex at all, e.g. like

inline bool throwX( std::string const& s )
{
    throw Failure( s );
}

template< class Predicate >
struct Accept: Predicate
{};

template< class Type, class Predicate >
inline bool operator>>( Type const& v, Accept< Predicate > const& isOK )
{
    return isOK( v );
}

struct IsNonNegative
{
    template< class Type >
    bool operator()( Type const& v ) const { return (v >= 0); }
};
Alf P. Steinbach
Hmm, yet another `>>` overload? Is that really what the world needs? ;)
jalf
+1 for the first paragraph.
Hans Passant
@jalf: I'm not aware of any other `>>` overloads (except in iostreams).
Alf P. Steinbach
@Alf: yeah, that's the one I'm referring to. That one is already fairly controversial. :)
jalf
And if we happen to be working in C where none of this is possible?
Len Holgate
@Len: I don't know a good answer to your question about C (at least when assuming you mean standard C), sorry. Happily the OP's question was about C++. C lacks automated cleanup, and I'd probably be as a fish on land if I tried to code C with my current habits! :-)
Alf P. Steinbach
My point was that initialising the variable is something that everyone can do. I don't disagree with your point that we should be declaring the variable at point of first use, or that exceptions are likely a better route...
Len Holgate