
liblzma.dll and mixing C runtimes (CRTs)
----------------------------------------

    If possible, liblzma.dll should be linked against the same CRT
    (MSVCRT or UCRT) as the application calling the liblzma functions.
    When this isn't possible, liblzma.dll will still work but there
    are a few API functions that need extra care.

    Each CRT has its own memory allocator, stdio FILE implementation,
    mapping of file descriptors from _open() to Windows' HANDLEs, and
    so on. Mixing CRTs is a problem if, for example, one library calls
    fopen() and then passes the resulting FILE* to a second library and
    these two libraries use different CRTs. liblzma doesn't expose FILE
    pointers or file descriptors in the API but the problem can occur
    with memory allocation with a few specific functions.

    The most commonly-used API functions in liblzma are such that both
    memory allocation and deallocation is done internally by liblzma,
    thus most applications won't have any problems with mixing CRTs
    with liblzma.dll. The following API functions are the exception:

        lzma/block.h:
            lzma_block_header_decode

        lzma/filter.h:
            lzma_filters_copy
            lzma_filters_free
            lzma_properties_decode
            lzma_filter_flags_decode
            lzma_str_to_filters
            lzma_str_from_filters
            lzma_str_list_filters

    Excluding lzma_filters_free(), the above functions allocate memory
    and leave it to the caller to free it. lzma_filters_free() frees
    memory given to it, and that memory may have been allocated outside
    of liblzma.

    For example, if application calls lzma_str_list_filters(&ptr, ...)
    and then uses free(ptr), something bad (memory corruption, crash)
    will happen if the application and liblzma.dll aren't using the
    same CRT. This can be worked around with a few lines of extra code.

    All these functions (and many others too) take a pointer to
    lzma_allocator structure as an argument. Typically it is set to
    NULL to let liblzma use malloc() and free() (and also calloc()
    as it is faster than malloc() + memset()). A custom lzma_allocator
    can be used to wrap malloc() and free() from application's CRT:

        static void * LZMA_API_CALL
        my_alloc(void *opaque, size_t nmemb, size_t size)
        {
            // liblzma guarantees that this won't overflow.
            return malloc(nmemb * size);
        }

        static void LZMA_API_CALL
        my_free(void *opaque, void *ptr)
        {
            free(ptr);
        }

        static const lzma_allocator allocator
                = { &my_alloc, &my_free, NULL };

    By passing &allocator to the problematic functions, CRT mixing
    should not cause any problems. There is no need to use &allocator
    with functions other than those listed above.

