diff options
author | Aliaksey Kandratsenka <alkondratenko@gmail.com> | 2024-06-11 18:54:45 -0400 |
---|---|---|
committer | Aliaksey Kandratsenka <alkondratenko@gmail.com> | 2024-06-11 19:09:09 -0400 |
commit | 778df41889eb562bb5e7e64526824a2604d832f9 (patch) | |
tree | 3ab77ed39aa5630294e7dc333155cd010e39dc91 | |
parent | cb2a58fb1ba2eea7f000f680be021ab45347b188 (diff) | |
download | google-perftools-778df41889eb562bb5e7e64526824a2604d832f9.tar.gz google-perftools-778df41889eb562bb5e7e64526824a2604d832f9.zip |
unbreak calloc memsetting extra memory in emergency malloc mode
-rw-r--r-- | src/tcmalloc.cc | 14 | ||||
-rw-r--r-- | src/tests/tcmalloc_unittest.cc | 11 |
2 files changed, 23 insertions, 2 deletions
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index c51a351..60f5e9b 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -1510,7 +1510,19 @@ ALWAYS_INLINE void* do_calloc(size_t n, size_t elem_size) { void* result = do_malloc_or_cpp_alloc(size); if (result != NULL) { - memset(result, 0, tc_nallocx(size, 0)); + size_t total_size = size; + if (!tcmalloc::IsEmergencyPtr(result)) { + // On windows we support recalloc (which was apparently + // originally introduced in Irix). In order for recalloc to work + // we need to zero-out not just the size we were asked for, but + // entire usable size. See also + // https://github.com/gperftools/gperftools/pull/994. + // + // But we can do it only when not dealing with emergency + // malloc-ed memory. + total_size = tc_nallocx(size, 0); + } + memset(result, 0, total_size); } return result; } diff --git a/src/tests/tcmalloc_unittest.cc b/src/tests/tcmalloc_unittest.cc index 85fde79..c03315e 100644 --- a/src/tests/tcmalloc_unittest.cc +++ b/src/tests/tcmalloc_unittest.cc @@ -1604,19 +1604,26 @@ TEST(TCMallocTest, EmergencyMallocNoHook) { void* p1 = noopt(tc_malloc)(32); void* p2 = nullptr; void* p3 = nullptr; + void* p4 = nullptr; portal->WithEmergencyMallocEnabled([&] () { p2 = noopt(malloc)(32); - p3 = tc_calloc(4096, 1024); + for (int i = 11; i < 999; i++) { + free(p3); + p3 = tc_calloc(1, i); + } + p4 = tc_calloc(4096, 1024); }); ASSERT_NE(p2, nullptr); ASSERT_NE(p3, nullptr); + ASSERT_NE(p4, nullptr); // Emergency malloc doesn't return pointers recognized by MallocExtension ASSERT_EQ(MallocExtension::instance()->GetOwnership(p1), MallocExtension::kOwned); ASSERT_EQ(MallocExtension::instance()->GetOwnership(p2), MallocExtension::kNotOwned); ASSERT_EQ(MallocExtension::instance()->GetOwnership(p3), MallocExtension::kNotOwned); + ASSERT_EQ(MallocExtension::instance()->GetOwnership(p4), MallocExtension::kNotOwned); SetNewHook(); SetDeleteHook(); @@ -1627,6 +1634,8 @@ TEST(TCMallocTest, EmergencyMallocNoHook) { // Emergency malloc automagically does the right thing for free() // calls and doesn't invoke hooks. + tc_free(p4); + tc_free(p3); tc_free(p2); ASSERT_EQ(g_DeleteHook_calls, 0); |