Merge "Add the timestamps for each alloc data"
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index a829a09..8a77170 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -28,6 +28,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
@@ -52,40 +53,51 @@
return dprintf(fd, "%d: thread_done 0x0\n", tid_) > 0;
}
-AllocEntry::AllocEntry(void* pointer) : pointer_(pointer) {}
+AllocEntry::AllocEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
+ : pointer_(pointer), start_ns_(start_ns), end_ns_(end_ns) {}
-MallocEntry::MallocEntry(void* pointer, size_t size) : AllocEntry(pointer), size_(size) {}
+MallocEntry::MallocEntry(void* pointer, size_t size, uint64_t start_ns, uint64_t end_ns)
+ : AllocEntry(pointer, start_ns, end_ns), size_(size) {}
bool MallocEntry::Write(int fd) const {
- return dprintf(fd, "%d: malloc %p %zu\n", tid_, pointer_, size_) > 0;
+ return dprintf(fd, "%d: malloc %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, size_,
+ start_ns_, end_ns_) > 0;
}
-FreeEntry::FreeEntry(void* pointer) : AllocEntry(pointer) {}
+FreeEntry::FreeEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
+ : AllocEntry(pointer, start_ns, end_ns) {}
bool FreeEntry::Write(int fd) const {
- return dprintf(fd, "%d: free %p\n", tid_, pointer_) > 0;
+ return dprintf(fd, "%d: free %p %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, start_ns_, end_ns_) >
+ 0;
}
-CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size)
- : MallocEntry(pointer, size), nmemb_(nmemb) {}
+CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size, uint64_t start_ns,
+ uint64_t end_ns)
+ : MallocEntry(pointer, size, start_ns, end_ns), nmemb_(nmemb) {}
bool CallocEntry::Write(int fd) const {
- return dprintf(fd, "%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_) > 0;
+ return dprintf(fd, "%d: calloc %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, nmemb_,
+ size_, start_ns_, end_ns_) > 0;
}
-ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer)
- : MallocEntry(pointer, size), old_pointer_(old_pointer) {}
+ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t start_ns,
+ uint64_t end_ns)
+ : MallocEntry(pointer, size, start_ns, end_ns), old_pointer_(old_pointer) {}
bool ReallocEntry::Write(int fd) const {
- return dprintf(fd, "%d: realloc %p %p %zu\n", tid_, pointer_, old_pointer_, size_) > 0;
+ return dprintf(fd, "%d: realloc %p %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
+ old_pointer_, size_, start_ns_, end_ns_) > 0;
}
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
-MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
- : MallocEntry(pointer, size), alignment_(alignment) {}
+MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t start_ns,
+ uint64_t end_ns)
+ : MallocEntry(pointer, size, start_ns, end_ns), alignment_(alignment) {}
bool MemalignEntry::Write(int fd) const {
- return dprintf(fd, "%d: memalign %p %zu %zu\n", tid_, pointer_, alignment_, size_) > 0;
+ return dprintf(fd, "%d: memalign %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
+ alignment_, size_, start_ns_, end_ns_) > 0;
}
struct ThreadData {
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index 43dba6a..484d73b 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -68,19 +68,23 @@
class AllocEntry : public RecordEntry {
public:
- explicit AllocEntry(void* pointer);
+ explicit AllocEntry(void* pointer, uint64_t st, uint64_t et);
virtual ~AllocEntry() = default;
protected:
void* pointer_;
+ // The start/end time of this operation.
+ uint64_t start_ns_;
+ uint64_t end_ns_;
+
private:
BIONIC_DISALLOW_COPY_AND_ASSIGN(AllocEntry);
};
class MallocEntry : public AllocEntry {
public:
- MallocEntry(void* pointer, size_t size);
+ MallocEntry(void* pointer, size_t size, uint64_t st, uint64_t et);
virtual ~MallocEntry() = default;
bool Write(int fd) const override;
@@ -94,7 +98,7 @@
class FreeEntry : public AllocEntry {
public:
- explicit FreeEntry(void* pointer);
+ explicit FreeEntry(void* pointer, uint64_t st, uint64_t et);
virtual ~FreeEntry() = default;
bool Write(int fd) const override;
@@ -105,7 +109,7 @@
class CallocEntry : public MallocEntry {
public:
- CallocEntry(void* pointer, size_t size, size_t nmemb);
+ CallocEntry(void* pointer, size_t size, size_t nmemb, uint64_t st, uint64_t et);
virtual ~CallocEntry() = default;
bool Write(int fd) const override;
@@ -119,7 +123,7 @@
class ReallocEntry : public MallocEntry {
public:
- ReallocEntry(void* pointer, size_t size, void* old_pointer);
+ ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t st, uint64_t et);
virtual ~ReallocEntry() = default;
bool Write(int fd) const override;
@@ -134,7 +138,7 @@
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
class MemalignEntry : public MallocEntry {
public:
- MemalignEntry(void* pointer, size_t size, size_t alignment);
+ MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t st, uint64_t et);
virtual ~MemalignEntry() = default;
bool Write(int fd) const override;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 617858a..7c68242 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -68,6 +68,100 @@
bool* g_zygote_child;
const MallocDispatch* g_dispatch;
+
+static __always_inline uint64_t Nanotime() {
+ struct timespec t = {};
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+
+namespace {
+// A TimedResult contains the result of from malloc end_ns al. functions and the
+// start/end timestamps.
+struct TimedResult {
+ uint64_t start_ns = 0;
+ uint64_t end_ns = 0;
+ union {
+ size_t s;
+ int i;
+ void* p;
+ } v;
+
+ uint64_t GetStartTimeNS() const { return start_ns; }
+ uint64_t GetEndTimeNS() const { return end_ns; }
+ void SetStartTimeNS(uint64_t t) { start_ns = t; }
+ void SetEndTimeNS(uint64_t t) { end_ns = t; }
+
+ template <typename T>
+ void setValue(T);
+ template <>
+ void setValue(size_t s) {
+ v.s = s;
+ }
+ template <>
+ void setValue(int i) {
+ v.i = i;
+ }
+ template <>
+ void setValue(void* p) {
+ v.p = p;
+ }
+
+ template <typename T>
+ T getValue() const;
+ template <>
+ size_t getValue<size_t>() const {
+ return v.s;
+ }
+ template <>
+ int getValue<int>() const {
+ return v.i;
+ }
+ template <>
+ void* getValue<void*>() const {
+ return v.p;
+ }
+};
+
+class ScopedTimer {
+ public:
+ ScopedTimer(TimedResult& res) : res_(res) { res_.start_ns = Nanotime(); }
+
+ ~ScopedTimer() { res_.end_ns = Nanotime(); }
+
+ private:
+ TimedResult& res_;
+};
+
+} // namespace
+
+template <typename MallocFn, typename... Args>
+static TimedResult TimerCall(MallocFn fn, Args... args) {
+ TimedResult ret;
+ decltype((g_dispatch->*fn)(args...)) r;
+ if (g_debug->config().options() & RECORD_ALLOCS) {
+ ScopedTimer t(ret);
+ r = (g_dispatch->*fn)(args...);
+ } else {
+ r = (g_dispatch->*fn)(args...);
+ }
+ ret.setValue<decltype(r)>(r);
+ return ret;
+}
+
+template <typename MallocFn, typename... Args>
+static TimedResult TimerCallVoid(MallocFn fn, Args... args) {
+ TimedResult ret;
+ {
+ ScopedTimer t(ret);
+ (g_dispatch->*fn)(args...);
+ }
+ return ret;
+}
+
+#define TCALL(FUNC, ...) TimerCall(&MallocDispatch::FUNC, __VA_ARGS__);
+#define TCALLVOID(FUNC, ...) TimerCallVoid(&MallocDispatch::FUNC, __VA_ARGS__);
+
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
@@ -419,7 +513,7 @@
return InternalMallocUsableSize(pointer);
}
-static void* InternalMalloc(size_t size) {
+static TimedResult InternalMalloc(size_t size) {
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
debug_dump_heap(android::base::StringPrintf(
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
@@ -430,30 +524,35 @@
size = 1;
}
+ TimedResult result;
+
size_t real_size = size + g_debug->extra_bytes();
if (real_size < size) {
// Overflow.
errno = ENOMEM;
- return nullptr;
+ result.setValue<void*>(nullptr);
+ return result;
}
if (size > PointerInfoType::MaxSize()) {
errno = ENOMEM;
- return nullptr;
+ result.setValue<void*>(nullptr);
+ return result;
}
- void* pointer;
if (g_debug->HeaderEnabled()) {
- Header* header =
- reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
+ result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
+ Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
if (header == nullptr) {
- return nullptr;
+ return result;
}
- pointer = InitHeader(header, header, size);
+ result.setValue<void*>(InitHeader(header, header, size));
} else {
- pointer = g_dispatch->malloc(real_size);
+ result = TCALL(malloc, real_size);
}
+ void* pointer = result.getValue<void*>();
+
if (pointer != nullptr) {
if (g_debug->TrackPointers()) {
PointerData::Add(pointer, size);
@@ -466,7 +565,8 @@
memset(pointer, g_debug->config().fill_alloc_value(), bytes);
}
}
- return pointer;
+
+ return result;
}
void* debug_malloc(size_t size) {
@@ -479,16 +579,17 @@
ScopedDisableDebugCalls disable;
ScopedBacktraceSignalBlocker blocked;
- void* pointer = InternalMalloc(size);
+ TimedResult result = InternalMalloc(size);
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new MallocEntry(pointer, size));
+ g_debug->record->AddEntry(new MallocEntry(result.getValue<void*>(), size,
+ result.GetStartTimeNS(), result.GetEndTimeNS()));
}
- return pointer;
+ return result.getValue<void*>();
}
-static void InternalFree(void* pointer) {
+static TimedResult InternalFree(void* pointer) {
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
debug_dump_heap(android::base::StringPrintf(
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
@@ -530,6 +631,7 @@
PointerData::Remove(pointer);
}
+ TimedResult result;
if (g_debug->config().options() & FREE_TRACK) {
// Do not add the allocation until we are done modifying the pointer
// itself. This avoids a race if a lot of threads are all doing
@@ -537,15 +639,15 @@
// pointer from another thread, while still trying to free it in
// this function.
pointer = PointerData::AddFreed(pointer, bytes);
- if (pointer != nullptr) {
- if (g_debug->HeaderEnabled()) {
- pointer = g_debug->GetHeader(pointer)->orig_pointer;
- }
- g_dispatch->free(pointer);
+ if (pointer != nullptr && g_debug->HeaderEnabled()) {
+ pointer = g_debug->GetHeader(pointer)->orig_pointer;
}
+ result = TCALLVOID(free, pointer);
} else {
- g_dispatch->free(free_pointer);
+ result = TCALLVOID(free, free_pointer);
}
+
+ return result;
}
void debug_free(void* pointer) {
@@ -558,15 +660,16 @@
ScopedDisableDebugCalls disable;
ScopedBacktraceSignalBlocker blocked;
- if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new FreeEntry(pointer));
- }
-
if (!VerifyPointer(pointer, "free")) {
return;
}
- InternalFree(pointer);
+ TimedResult result = InternalFree(pointer);
+
+ if (g_debug->config().options() & RECORD_ALLOCS) {
+ g_debug->record->AddEntry(
+ new FreeEntry(pointer, result.GetStartTimeNS(), result.GetEndTimeNS()));
+ }
}
void* debug_memalign(size_t alignment, size_t bytes) {
@@ -588,6 +691,7 @@
return nullptr;
}
+ TimedResult result;
void* pointer;
if (g_debug->HeaderEnabled()) {
// Make the alignment a power of two.
@@ -610,7 +714,8 @@
return nullptr;
}
- pointer = g_dispatch->malloc(real_size);
+ result = TCALL(malloc, real_size);
+ pointer = result.getValue<void*>();
if (pointer == nullptr) {
return nullptr;
}
@@ -620,6 +725,7 @@
value += (-value % alignment);
Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
+ // Don't need to update `result` here because we only need the timestamps.
pointer = InitHeader(header, pointer, bytes);
} else {
size_t real_size = bytes + g_debug->extra_bytes();
@@ -628,7 +734,8 @@
errno = ENOMEM;
return nullptr;
}
- pointer = g_dispatch->memalign(alignment, real_size);
+ result = TCALL(memalign, alignment, real_size);
+ pointer = result.getValue<void*>();
}
if (pointer != nullptr) {
@@ -644,7 +751,8 @@
}
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
+ g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment,
+ result.GetStartTimeNS(), result.GetEndTimeNS()));
}
}
@@ -662,10 +770,12 @@
ScopedBacktraceSignalBlocker blocked;
if (pointer == nullptr) {
- pointer = InternalMalloc(bytes);
+ TimedResult result = InternalMalloc(bytes);
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
+ g_debug->record->AddEntry(new ReallocEntry(result.getValue<void*>(), bytes, nullptr,
+ result.GetStartTimeNS(), result.GetEndTimeNS()));
}
+ pointer = result.getValue<void*>();
return pointer;
}
@@ -674,11 +784,13 @@
}
if (bytes == 0) {
+ TimedResult result = InternalFree(pointer);
+
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
+ g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer, result.GetStartTimeNS(),
+ result.GetEndTimeNS()));
}
- InternalFree(pointer);
return nullptr;
}
@@ -697,6 +809,7 @@
return nullptr;
}
+ TimedResult result;
void* new_pointer;
size_t prev_size;
if (g_debug->HeaderEnabled()) {
@@ -730,7 +843,8 @@
}
// Allocate the new size.
- new_pointer = InternalMalloc(bytes);
+ result = InternalMalloc(bytes);
+ new_pointer = result.getValue<void*>();
if (new_pointer == nullptr) {
errno = ENOMEM;
return nullptr;
@@ -738,14 +852,18 @@
prev_size = header->usable_size;
memcpy(new_pointer, pointer, prev_size);
- InternalFree(pointer);
+ TimedResult free_time = InternalFree(pointer);
+ // `realloc` is split into two steps, update the end time to the finish time
+ // of the second operation.
+ result.SetEndTimeNS(free_time.GetEndTimeNS());
} else {
if (g_debug->TrackPointers()) {
PointerData::Remove(pointer);
}
prev_size = g_dispatch->malloc_usable_size(pointer);
- new_pointer = g_dispatch->realloc(pointer, real_size);
+ result = TCALL(realloc, pointer, real_size);
+ new_pointer = result.getValue<void*>();
if (new_pointer == nullptr) {
return nullptr;
}
@@ -767,7 +885,8 @@
}
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
+ g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer, result.GetStartTimeNS(),
+ result.GetEndTimeNS()));
}
return new_pointer;
@@ -807,21 +926,24 @@
}
void* pointer;
+ TimedResult result;
if (g_debug->HeaderEnabled()) {
// Need to guarantee the alignment of the header.
- Header* header =
- reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
+ result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
+ Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
if (header == nullptr) {
return nullptr;
}
memset(header, 0, g_dispatch->malloc_usable_size(header));
pointer = InitHeader(header, header, size);
} else {
- pointer = g_dispatch->calloc(1, real_size);
+ result = TCALL(calloc, 1, real_size);
+ pointer = result.getValue<void*>();
}
if (g_debug->config().options() & RECORD_ALLOCS) {
- g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
+ g_debug->record->AddEntry(
+ new CallocEntry(pointer, bytes, nmemb, result.GetStartTimeNS(), result.GetEndTimeNS()));
}
if (pointer != nullptr && g_debug->TrackPointers()) {
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index c6378f5..6215379 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -184,6 +184,23 @@
return diff;
}
+static void VerifyRecords(std::vector<std::string>& expected, std::string& actual) {
+ size_t offset = 0;
+ for (std::string& str : expected) {
+ ASSERT_STREQ(str.c_str(), actual.substr(offset, str.size()).c_str());
+ if (str.find("thread_done") != std::string::npos) {
+ offset = actual.find_first_of("\n", offset) + 1;
+ continue;
+ }
+ offset += str.size() + 1;
+ uint64_t st = strtoull(&actual[offset], nullptr, 10);
+ offset = actual.find_first_of(" ", offset) + 1;
+ uint64_t et = strtoull(&actual[offset], nullptr, 10);
+ ASSERT_GT(et, st);
+ offset = actual.find_first_of("\n", offset) + 1;
+ }
+}
+
void VerifyAllocCalls(bool all_options) {
size_t alloc_size = 1024;
@@ -2171,61 +2188,61 @@
#endif
void VerifyRecordAllocs(const std::string& record_filename) {
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_calloc(1, 20);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: calloc %p 20 1\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: calloc %p 20 1", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_realloc(nullptr, 30);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: realloc %p 0x0 30\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: realloc %p 0x0 30", getpid(), pointer));
void* old_pointer = pointer;
pointer = debug_realloc(pointer, 2048);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: realloc %p %p 2048\n", getpid(),
- pointer, old_pointer);
+ expected.push_back(
+ android::base::StringPrintf("%d: realloc %p %p 2048", getpid(), pointer, old_pointer));
debug_realloc(pointer, 0);
- expected += android::base::StringPrintf("%d: realloc 0x0 %p 0\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: realloc 0x0 %p 0", getpid(), pointer));
pointer = debug_memalign(16, 40);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 16 40\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 16 40", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_aligned_alloc(32, 64);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 32 64\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 32 64", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 32 50", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
pointer = debug_pvalloc(60);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 4096 4096\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 4096 4096", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_valloc(70);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 4096 70\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: memalign %p 4096 70", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
#endif
// Dump all of the data accumulated so far.
@@ -2235,7 +2252,7 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -2256,23 +2273,23 @@
TEST_F(MallocDebugTest, record_allocs_max) {
InitRecordAllocs("record_allocs=5");
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_malloc(20);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 20\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 20", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
pointer = debug_malloc(1024);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 1024\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 1024", getpid(), pointer));
debug_free(pointer);
// Dump all of the data accumulated so far.
@@ -2282,7 +2299,7 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ(
@@ -2303,9 +2320,10 @@
});
thread.join();
- std::string expected = android::base::StringPrintf("%d: malloc %p 100\n", tid, pointer);
- expected += android::base::StringPrintf("%d: free %p\n", tid, pointer);
- expected += android::base::StringPrintf("%d: thread_done 0x0\n", tid);
+ std::vector<std::string> expected;
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 100", tid, pointer));
+ expected.push_back(android::base::StringPrintf("%d: free %p", tid, pointer));
+ expected.push_back(android::base::StringPrintf("%d: thread_done 0x0", tid));
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
@@ -2314,7 +2332,7 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -2329,13 +2347,13 @@
ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", record_filename.c_str()));
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
// Dump all of the data accumulated so far.
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
@@ -2351,7 +2369,8 @@
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
std::string expected_log = android::base::StringPrintf(
@@ -2375,13 +2394,13 @@
TEST_F(MallocDebugTest, record_allocs_write_entries_does_not_allocate) {
InitRecordAllocs("record_allocs=5");
- std::string expected;
+ std::vector<std::string> expected;
void* pointer = debug_malloc(10);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
debug_free(pointer);
- expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+ expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
malloc_disable();
kill(getpid(), SIGRTMAX - 18);
@@ -2389,7 +2408,8 @@
std::string actual;
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
- ASSERT_STREQ(expected.c_str(), actual.c_str());
+
+ VerifyRecords(expected, actual);
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());