Profil von Robert DunlopRobert Dunlop's SpaceFotosBlogListenMehr Extras Hilfe

Blog


    02 Juli

    Chages to ATL effecting string conversion code

    Having spent some time tracking down a bug that resulted from code that failed due to changes in ATL, I thought I should post a bit about it in case others should find this information useful to avoid the same pitfall that I ran into.
     
    The problem stemmed from code that was valid when it was originally written using ATL 3.0's string conversion macros, but when the project was updated to Visual Studio 2005 with ATL 8.0 the code resulted in referencing a pointer to a de-allocated buffer.  The original code looked something like this:

    // copy name into new buffer
    LPTSTR str=COLE2T(name);
    m_blockName=new wchar_t[wcslen(str)+1];
    wcscpy(m_blockName,str);

    However, after migrating the code, I kept running into intermittent problems that appeared to be related to memory corruption.  As it turns out, changes in ATL cause the temporary string generated by COLE2T to be de-allocated immediately after the assignment statement completes, so that the pointer in str is no longer valid when we try to use it in subsequent lines.  In the previous version of ATL this code was originally written for, the pointer was not released until the end of the function that it is created in, so there was no issue with this usage.
     
    The changes to ATL involved are documented here:
     
    Fixing the problem, once I found it, was pretty simple, the corrected code is shown below:
     

    // copy name into new buffer
    COLE2T str(name);
    m_blockName=new wchar_t[wcslen(str)+1];
    wcscpy(m_blockName,str);

     

    Note that code which uses these conversions in-line within an expression, for example as a parameter to another function, do not need to be modified.  For example, this code is still valid under current ATL versions:

    // open the specified file
    HANDLE hFile=CreateFile(COLE2T(fileName),
                                         FILE_READ_DATA,
                                         FILE_SHARE_READ,
                                         NULL,
                                         OPEN_EXISTING,
                                         FILE_ATTRIBUTE_NORMAL,
                                         NULL);

    08 Januar

    Sharing DLL data between apps in a DLL

    An interesting tidbit in this article:
     
    The second Q&A section shows how to share global data in a DLL between applications that load the DLL.  Normally each application gets a unique copy of the global variables defined in a DLL, so that changes only effect the values of these variables seen by the application that caused the changes.  To change this behavior for certain variables that you want to be shared between all applications using the DLL, you can define a data segment for these variables and mark it as shared, like:
     
    // in dll code
    #pragma data seg (".mySharedSegment")
    int sharedValue=0;
    #pragma data seg ()
    #pragma comment(linker,"/SECTION:.mySharedSegment,RWS")
     
    Variables outside of the pragma block retain the normal behavior, that is, each applidation gets a unique copy of variables not specified in the pragma block.
     
    Note that once all applications have unloaded the DLL the shared values will be lost, and re-initialized when the DLL is loaded again, so there is only persistence while at least one application has the DLL loaded.  This could be useful for a system-wide singleton that is created on-demand.  The singleton would be declared as a shared variable, and an accessor function would return a pointer to the shared singleton:
     
    #pragma data seg (".SharedSingletonSegment")
    mySingletonClass SharedInstance;
    #pragma data seg ()
    #pragma comment(linker,"/SECTION:.SharedSingletonSegment,RWS")
     
    mySingletonClass *GetSingleton()
    {
         return &SharedInstance;
    }
     
    One could also dynamically create the singleton instance the first time it is requested, though this would require that the singleton class be reference counted and released each time an application unloads the DLL.
     
    Be sure to consider that the same care would need to be used with values shared in a DLL as one would apply to multithreaded variable access.  This would likely mean that synchronization objects such as critical sections would need to be defined as shared variables in the DLL as well.