From 6371fccdbe34ac214f54a8843dc6d2c9f1e05d92 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 15 Feb 2016 11:46:13 +0100 Subject: [PATCH] Cycles: Fix guarded allocator issues on Windows The issue was caused by static vectors allocating some internal data using rebound element allocator for them, which was causing access to a non-initialized statistics objects and was failing a lot when switching Blender to a fully guarded allocation. Additionally, we were not able to free that internal memory before Blender exits, which was causing false-positive memory leak prints. Now we're not using GuardedAllocator for those proxy containers. Ideally this should be done as a GuardedAllocator::rebind, but it didn't work for vector because it seems some internal parts are converting bool to char32_t, which either makes it so we can't use GuardedAllocator for those vectors or the compiler get's confused when we're trying explicitly allow GuardedAllocator for rebind. This with current approach we should be fine for the release. --- intern/cycles/util/util_guarded_allocator.h | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h index 484aa3a8cce..ad1eb6f657f 100644 --- a/intern/cycles/util/util_guarded_allocator.h +++ b/intern/cycles/util/util_guarded_allocator.h @@ -123,6 +123,34 @@ public: inline bool operator==(GuardedAllocator const& /*other*/) { return true; } inline bool operator!=(GuardedAllocator const& other) { return !operator==(other); } + +#ifdef _MSC_VER + /* Welcome to the black magic here. + * + * The issue is that MSVC C++ allocates container proxy on any + * vector initialization, including static vectors which don't + * have any data yet. This leads to several issues: + * + * - Static objects initialization fiasco (global_stats from + * util_stats.h might not be initialized yet). + * - If main() function changes allocator type (for example, + * this might happen with `blender --debug-memory`) nobody + * will know how to convert already allocated memory to a new + * guarded allocator. + * + * Here we work this around by making it so container proxy does + * not use guarded allocation. A bit fragile, unfortunately. + */ + template<> + struct rebind { + typedef std::allocator other; + }; + + operator std::allocator() const + { + return std::allocator(); + } +#endif }; /* Get memory usage and peak from the guarded STL allocator. */