the1's WebLog

  • More on Getting the Number of Array Elements

    In a previous post, I discussed a safer way to get the number of elements in a C++ array.  I mentioned that the countof() macro doesn’t work with local types (i.e. types defined inside a function definition).

     

    I just realized that the macro also fails to work with anonymous types under certain circumstances.  To be exact, If you call countof() on two arrays that have different anonymous types AND same size, then the second call will fail to compile.

    e.g.

     

    struct

    {

        int x;

    } g_a[100];

     

    struct

    {

        int x;

    } g_b[100];

     

     

        int g_size;

       

        g_size = countof( g_a );  // First call - OK

        g_size = countof( g_b );  // Second call - compiler ERROR!

     

    The reason is that in this case, the second instantiation of the template helper function _ArraySizeHelper clashes with the first instantiation.

     

    Note that if you change the size of g_b to something other than 100, it compiles fine.

     

    So the caveat should be “countof() does not work with local types, and under certain circumstances does not work with anonymous types.”

     

    I cannot believe it’s so difficult to get such a simple job (getting the number of array elements) done in C++.

     

    What a broken language it is.

  • Programming in XSLT!

    Not so long ago, I posted a programming challenge, and received solutions in many different languages.  Just when I thought people had forgot about this, I got this one from Anton Triest.  It was written in a programming language called ... (surprise) XSLT!

    Ask not what you can do in XSLT; ask what you cannot do in XSLT. :-)

    (For those of you concerned that you need to buy an XSLT compiler to try it out, take heart -- all you need is your web browser)

     

     

  • Generalize Smart Pointers in C++

    After programming in C++ for a while, you will inevitably be introduced to the concept of “smart pointers” (or you will discover them on your own).  These are pointers that know to automatically release the objects they point to when they (the pointers) are destructed.  They have proved quite handy in avoiding memory leaks.

     

    The most well known implementation of smart pointers probably is auto_ptr in STL and CAutoPtr in ATL, which will delete the object upon destruction.

     

    auto_ptr and CAutoPtr are fine, but they have limitations:

     

    1. Sometimes the pointer is not allocated via the new operator (e.g. malloc()).  In these cases, you don’t want to use auto_ptr or CAutoPtr as the pointer will by wrongfully deleted (as opposed to be free()-ed in the case of malloc()).
    2. They are good for wrapping pointers only.  In general, you would like to allocate some resource and have the compiler release it for you automatically.

     

    Why not generalize smart pointers to smart resource managers?  It’s actually easy to do so.  Here’s my take on this:

     

    ///////////////////////////////////////////////////////////

    // Class CAutoResource

    //

    // An object of this template class holds a resource, and will dispose of

    // the resource when it is destructed.  This class is a generalization of

    // auto_ptr in STL and CAutoPtr in ATL.  The user must supply the function

    // doing the disposition as a template parameter.

    //

    // Examples where this class can be useful include file/window/registry

    // handles and pointers.

     

    template< typename T, void (*Dispose)( T ), const T NullResource = 0>

    class CAutoResource

    {

    public:

        typedef T ResourceType;

          CAutoResource( T Resource = NullResource )

                : m_Resource( Resource )

          {

          }

     

        ~CAutoResource()

        {

            if ( NullResource != m_Resource )

            {

                Dispose( m_Resource );

            }

        }

     

        operator T() const

        {

            return m_Resource;

        }

     

        T Get() const

        {

            return m_Resource;

        }

     

        void Attach( T NewResource )

        {

            Dispose( m_Resource );

            m_Resource = NewResource;

        }

     

          // The assert on operator & usually indicates a bug.

        T * operator & ()

        {

            _ASSERTE( NullResource == m_Resource );

            return & m_Resource;

        }

     

    private:

        T   m_Resource;

     

        CAutoResource( const CAutoResource& );

        CAutoResource& operator = ( const CAutoResource& );

    };

     

    To use the CAutoResource template class, you need to supply:

     

    1. The type of the resource;
    2. A function that disposes of the resource; and
    3. (Optional) The value that represents the “null” resource.  If you don’t specify it, 0 is used.

     

    Upon destruction, the resource in a CAutoResource object will be released by calling the resource disposition function.

     

    I hope it becomes obvious to you that auto_ptr and CAutoPtr are basically special cases of CAutoResource where the disposition function is the delete operator.  They do have more member functions, but those are not hard to add.

     

    Let’s see some examples of using CAutoResource.

     

    The first one is to wrap the generic Windows HANDLE, which is used by the Win32 API to represent a lot of different things (windows, fonts, brushes, memory, and etc).  A typedef instantiates CAutoResource for this scenario:

     

    #include <windows.h>

     

    // Generic Windows handle

    void DisposeHandle( HANDLE handle )

    {

        if ( NULL != handle )

        {

            CloseHandle( handle );

        }

    }

     

    typedef CAutoResource< HANDLE, DisposeHandle >  CAutoHandle;

     

    Our second example is handle to a registry key:

     

    // Handle to registry key

    void DisposeHKey( HKEY hKey )

    {

        if ( NULL != hKey )

        {

            RegCloseKey( hKey );

        }

    }

     

    typedef CAutoResource< HKEY, DisposeHKey >  CAutoHKey;

     

    Sometimes, two resources have the same C++ type but different semantics and should be released in different manners.  For example, an HINTERNET should be released by either WinHttpCloseHandle() or InternetCloseHandle(), depending on whether it was allocated using the WinHttp or the WinINet API.  This is no problem for us, as the disposition function is a type parameter to CAutoResource and you can specify different functions for the same C++ type:

     

    #include <winhttp.h>

     

    // Internet handle opened via the WinHttp API

    void DisposeWinHttpHandle( HINTERNET handle )

    {

        if ( NULL != handle )

        {

            WinHttpCloseHandle( handle );

        }

    }

     

    typedef CAutoResource< HINTERNET, DisposeWinHttpHandle > CAutoHWinHttp;

     

    #include <wininet.h>

     

    // Internet handle opened via the WinINet API

    void DisposeHInternet( HINTERNET handle )

    {

        if ( NULL != handle )

        {

            InternetCloseHandle( handle );

        }

    }

     

    typedef CAutoResource< HINTERNET, DisposeHInternet >  CAutoHInternet;

     

    Let’s give one example where the resource we want to manage is a pointer:

     

    // Memory allocated via LocalAlloc() or LocalReAlloc()

    void DisposeLocalMem( LPVOID lpMem )

    {

        if ( NULL != lpMem )

        {

            LocalFree( lpMem );

        }

    }

     

    typedef CAutoResource< LPVOID, DisposeLocalMem > CAutoLocalMem;

     

    So far so good, but as soon as you try to dereference a pointer masqueraded as a CAutoResource, you’ll find we haven’t defined the dereference operator (*) and the arrow operator (->) yet.  This is because they don’t make sense in the context of general resources.

     

    What we can do is to define these operators in a sub-class of CAutoResource.  I would’ve called it CAutoPtr, but that name is taken, so instead we have CAutoPtrEx:

     

    ///////////////////////////////////////////////////////////

    // Class CAutoPtrEx

    //

    // An object of this template class holds a pointer, and will dispose of

    // the object pointed to when it is destructed.  This class is a

    // generalization of auto_ptr in STL and CAutoPtr in ATL.

    // It is preferred to auto_ptr and CAutoPtr when 'delete' is not the right

    // way to dispose of the object.  The user must supply the function doing

    // the disposition as a template parameter.

     

    template< typename T, void (*Dispose)( T * ) >

    class CAutoPtrEx : public CAutoResource< T *, Dispose, NULL >

    {

    public:

        CAutoPtrEx( T * ptr = NULL )

            : CAutoResource< T *, Dispose >( ptr )

        {}

     

        T& operator * () const

        {

            return *Get();

        }

     

        T * operator -> () const

        {

            return Get();

        }

    private:

        CAutoPtrEx( const CAutoPtrEx& );

        CAutoPtrEx& operator = ( const CAutoPtrEx& );

    };

     

    I’ll finish this article with an example using CAutoPtrEx:

     

    // Memory allocated via CoTaskMemAlloc() or CoTaskMemRealloc()

    template <typename T>

    class CComMem

    {

    public:

        static void Dispose( T * pMem )

        {

            if ( pMem )

            {

                ::CoTaskMemFree( pMem );

            }

        }

     

        typedef CAutoPtrEx< T, CComMem::Dispose > AutoPtr;

    };

     

    (This posting is provided "AS IS" with no warranties, and confers no rights.)

  • Top reasons for failing to download Visual Studio Express beta 1

    As you might know, now you can download Visual Studio express SKU's from here for free.

    Since the release last Monday, we have seen that some users failed to download this product.  The top reasons include:

    1. The user cancelled the download.

    Please be reminded that you are downloading a large product, for example, the documentation component (MSDN express) itself is over 150 MB.  And, given the volume of download we are receiving, sometimes the progress will be very slow and it may look like hanging.  Give it more time and you have a good chance of eventually finish the download.

    2. The BITS service is disabled on the machine.

    The VS express web setup relies on the BITS (Background Intelligent Transfer Service) service on the user's machine to download the setup files.  BITS is enabled by default when you install Windows, but some user may choose to disable it for “performance gain”.  This is not necessary as BITS is taking very little resource.  You need to enable BITS before trying to install VS express over the web.

    3. The user is not logged on.

    Some users are trying to run VS express web setup under other's identity by using the “runas” command.  This is not supported by BITS.  You have to be logged on interactively.  Another unsupported scenario is running the setup in a Terminal Server session into a Windows 2000 server machine.  (Terminal Server into Windows XP and Windows 2003 server is fine.)

  • Improve Longhorn code quality

    Starting the coming Monday (July 12, 2004), I will be working for the Windows devision instead of Visual Studio.  My new team is focusing on improving the quality of the Longhorn code base.  I might write more about it once I get an idea on what it is really like there.

    I would love to hear your suggestions and comments on best software development practice, and what you think we can do to improve the quality of a software project that involves millions of lines of code.  Do you have a story to share?  That would be great.