Returning XLOPERs That Still Need to Be Freed by Microsoft Excel

As explained in the previous section, it is important to call the xlFree function on any XLOPERs that return values from callback functions because Microsoft Excel may have allocated some memory for these values and needs to free this memory. For example, suppose we need a DLL function that returns the name of the current sheet. That DLL function calls GET.DOCUMENT(1) to get the name of the sheet. For example:

/*
** BAD!
*/
LPXLOPER WINAPI GetSheetName(void)
{
    static XLOPER x1, xSheetName;

    x1.xltype = xltypeInt;
    x1.val.w  = 1;

    Excel4(xlfGetDocument, &xSheetName, 1, (LPXLOPER) &x1);

    return (LPXLOPER)&xSheetName;
}

What's wrong with this code? It calls GET.DOCUMENT(1), which returns a string. This string is then allocated by Microsoft Excel. However, the code never calls xlFree on the return value, so Microsoft Excel loses the memory associated with the string. You can waste quite a bit of memory this way, and it can never be retrieved.

You could try calling the xlFree function on xSheetName before returning it. Unfortunately, the contents of an XLOPER are undefined after xlFree, so that probably wouldn't work. You could allocate your own static XLOPER, with your own, static buffer to keep the string. This would require copying out the data yourself, and would waste static (global) memory.

Microsoft Excel supports a special bit called xlbitXLFree (0x1000). You can turn on this bit in the xltype field of any XLOPER returned from Microsoft Excel. If your function returns an XLOPER in which the xlbitXLFree bit is 1, Microsoft Excel copies out the data it needs from the XLOPER and frees it for you. For example, you could rewrite the preceding function as:

/*
** GOOD!
*/
LPXLOPER WINAPI GetSheetName(void)
{
    static XLOPER x1, xSheetName;

    x1.xltype = xltypeInt;
    x1.val.w  = 1;

    Excel4(xlfGetDocument, &xSheetName, 1, (LPXLOPER) &x1);

    xSheetName.xltype |= xlbitXLFree;

    return (LPXLOPER)&xSheetName;
}

Microsoft Excel frees xSheetName for you after the function has returned.