aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAliaksey Kandratsenka <alkondratenko@gmail.com>2024-06-11 18:54:45 -0400
committerAliaksey Kandratsenka <alkondratenko@gmail.com>2024-06-11 19:09:09 -0400
commit778df41889eb562bb5e7e64526824a2604d832f9 (patch)
tree3ab77ed39aa5630294e7dc333155cd010e39dc91
parentcb2a58fb1ba2eea7f000f680be021ab45347b188 (diff)
downloadgoogle-perftools-778df41889eb562bb5e7e64526824a2604d832f9.tar.gz
google-perftools-778df41889eb562bb5e7e64526824a2604d832f9.zip
unbreak calloc memsetting extra memory in emergency malloc mode
-rw-r--r--src/tcmalloc.cc14
-rw-r--r--src/tests/tcmalloc_unittest.cc11
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);