Chilkat C++ — Memory Leaks
A frequent question from C++ developers, and why the answer is reassuring — on every platform Chilkat supports.
What is often mistaken for a memory leak is actually intentional memory caching used to improve performance.
Why memory stays allocated
Many Chilkat C++ classes initialize internal lookup tables, caches, or other shared data structures the first time they are needed. These allocations are made only once and are then reused by all subsequent Chilkat objects and method calls for the lifetime of the process. This avoids repeatedly allocating and freeing the same resources, improving both performance and scalability.
Because these shared structures intentionally remain allocated until the
application exits, Visual C++'s _CrtDumpMemoryLeaks() may report them as
memory leaks if it is called before the Chilkat library performs its final
cleanup. These are not true memory leaks — the memory is still owned by
the library and would normally be reclaimed automatically when the process
terminates.
Verifying your application has no leaks
The procedure is identical on every platform. If you want to confirm that your
application has no memory leaks, call CkSettings::cleanupMemory()
immediately before your program exits. This releases all internally cached resources
so that whatever leak detector you use — the Visual C++ CRT debug heap,
Valgrind, AddressSanitizer, the macOS leaks tool, CodeGuard, and so on
— reports only genuine leaks.
The one constant across all environments is CkSettings::cleanupMemory().
Only the leak-detection tool changes from platform to platform.
CkSettings::cleanupMemory()should be called only once, immediately before the application terminates.- After calling
cleanupMemory(), no other Chilkat methods may be called — including the destructors of any remaining Chilkat objects. Ensure all Chilkat objects have already gone out of scope or been destroyed before calling it.
Demonstrating that memory is stable
A good way to demonstrate that the library does not leak memory is to execute the same Chilkat operation repeatedly — for example, 100,000 times in a loop. Memory usage will initially increase as the shared internal structures are created, but it will then remain essentially constant, because those structures are reused rather than allocated again.
The universal pattern
Regardless of platform or compiler, the only Chilkat-specific requirement is to
call CkSettings::cleanupMemory() as the final Chilkat call before
your program exits, after every Chilkat object has been destroyed:
#include "CkSettings.h" #include "CkXml.h" void TestLoadXml() { CkXml xml; xml.LoadXmlFile("crisp.xml"); xml.SaveXml("out.xml"); } // 'xml' is destroyed here, before cleanupMemory(). int main() { TestLoadXml(); // Must be the final Chilkat call the program makes. CkSettings::cleanupMemory(); return 0; }
The C++ above does not change between environments. Only the build flags, the run command, and the leak detector differ, as shown next.
Leak detection by environment
Use the Visual C++ CRT debug heap. Build in the Debug configuration and
call _CrtDumpMemoryLeaks() after cleanupMemory():
#define _CRTDBG_MAP_ALLOC #include "stdafx.h" #include <stdio.h> #include <crtdbg.h> #include "CkSettings.h" #include "CkXml.h" void TestLoadXml() { CkXml xml; xml.LoadXmlFile("crisp.xml"); xml.SaveXml("out.xml"); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { TestLoadXml(); // This must be the final Chilkat call made by the application. CkSettings::cleanupMemory(); // Reports any remaining (genuine) allocations. _CrtDumpMemoryLeaks(); return 0; }
_CrtDumpMemoryLeaks() belongs to the MSVC debug runtime and is
not available with MinGW. Use AddressSanitizer (which includes
LeakSanitizer) instead, or a tool such as Dr. Memory. With the universal
main() shown above:
g++ -g -fsanitize=address main.cpp -lchilkat -o app
./app # LeakSanitizer prints any real leaks at exit
Two good options — choose either:
g++ -g main.cpp -lchilkat -o app valgrind --leak-check=full --show-leak-kinds=all ./app
g++ -g -fsanitize=address main.cpp -lchilkat -o app ./app
Use Apple's built-in leaks tool (or the Leaks instrument in
Xcode Instruments):
clang++ -g main.cpp -lchilkat -o app MallocStackLogging=1 leaks --atExit -- ./app
On modern macOS, Valgrind has little or no support (especially
on Apple Silicon), and LeakSanitizer is unreliable on Apple Silicon, so
the leaks tool or Instruments is recommended. Do not combine
leaks with -fsanitize=address.
Apps don't exit the way command-line programs do, so leak checking is usually
done in a test harness. Use the Leaks instrument in Xcode Instruments, or
enable Address Sanitizer / Malloc Stack Logging in your scheme's
Diagnostics tab. Call CkSettings::cleanupMemory() at the end
of your test run (after all Chilkat objects are gone) before measuring.
Build your native library with the NDK's AddressSanitizer (which
includes LeakSanitizer), or use malloc_debug. Add the sanitizer flag
to your native build and call CkSettings::cleanupMemory() before your
native code finishes:
target_compile_options(yourlib PRIVATE -fsanitize=address -g) target_link_options(yourlib PRIVATE -fsanitize=address)
Enable CodeGuard (the built-in runtime memory checker) in
Project → Options → C++ Compiler → CodeGuard,
then call CkSettings::cleanupMemory() before the program exits so
CodeGuard reports only genuine leaks.