Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrf fromlist] [app] Fix DeferredAttributePersister memory leak #369

Merged
merged 2 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions config/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,13 @@ config CHIP_MALLOC_SYS_HEAP_WATERMARKS_SUPPORT
Enables support for getting current heap high watermark and resetting
watermarks.

config CHIP_MALLOC_SYS_HEAP_DEBUG
bool "Log every allocated or freed memory block"
help
Enables debug logs printed whenever a heap memory block is allocated or
freed. The logs can be used to trace the source of memory leaks in the
application.

endif

module = MATTER
Expand Down
2 changes: 1 addition & 1 deletion src/app/DeferredAttributePersistenceProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void DeferredAttribute::Flush(AttributePersistenceProvider & persister)
{
VerifyOrReturn(IsArmed());
persister.WriteValue(mPath, ByteSpan(mValue.Get(), mValue.AllocatedSize()));
mValue.Release();
mValue.Free();
}

CHIP_ERROR DeferredAttributePersistenceProvider::WriteValue(const ConcreteAttributePath & aPath, const ByteSpan & aValue)
Expand Down
4 changes: 2 additions & 2 deletions src/darwin/Framework/CHIP/MTRBaseDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1141,8 +1141,8 @@ - (void)readAttributePaths:(NSArray<MTRAttributeRequestPath *> * _Nullable)attri
//
callback->AdoptReadClient(std::move(readClient));
callback.release();
attributePathParamsList.Release();
eventPathParamsList.Release();
IgnoreUnusedVariable(attributePathParamsList.Release());
IgnoreUnusedVariable(eventPathParamsList.Release());
return err;
});
std::move(*bridge).DispatchAction(self);
Expand Down
30 changes: 21 additions & 9 deletions src/lib/support/ScopedBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#pragma once

#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>

#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -84,10 +85,11 @@ class ScopedMemoryBufferBase
const void * Ptr() const { return mBuffer; }

/**
* Releases the undelying buffer. Buffer stops being managed and will not be
* auto-freed.
* Releases the underlying buffer.
*
* The buffer stops being managed and will not be auto-freed.
*/
void * Release()
CHECK_RETURN_VALUE void * Release()
{
void * buffer = mBuffer;
mBuffer = nullptr;
Expand Down Expand Up @@ -139,13 +141,18 @@ class ScopedMemoryBuffer : public Impl::ScopedMemoryBufferBase<MemoryManagement>

static_assert(std::is_trivially_destructible<T>::value, "Destructors won't get run");

inline T * Get() { return static_cast<T *>(Base::Ptr()); }
inline T & operator[](size_t index) { return Get()[index]; }
T * Get() { return static_cast<T *>(Base::Ptr()); }
T & operator[](size_t index) { return Get()[index]; }

inline const T * Get() const { return static_cast<const T *>(Base::Ptr()); }
inline const T & operator[](size_t index) const { return Get()[index]; }
const T * Get() const { return static_cast<const T *>(Base::Ptr()); }
const T & operator[](size_t index) const { return Get()[index]; }

inline T * Release() { return static_cast<T *>(Base::Release()); }
/**
* Releases the underlying buffer.
*
* The buffer stops being managed and will not be auto-freed.
*/
CHECK_RETURN_VALUE T * Release() { return static_cast<T *>(Base::Release()); }

ScopedMemoryBuffer & Calloc(size_t elementCount)
{
Expand Down Expand Up @@ -222,7 +229,12 @@ class ScopedMemoryBufferWithSize : public ScopedMemoryBuffer<T>
ScopedMemoryBuffer<T>::Free();
}

T * Release()
/**
* Releases the underlying buffer.
*
* The buffer stops being managed and will not be auto-freed.
*/
CHECK_RETURN_VALUE T * Release()
{
T * buffer = ScopedMemoryBuffer<T>::Release();
mCount = 0;
Expand Down
20 changes: 18 additions & 2 deletions src/platform/Zephyr/SysHeapMalloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ void * Malloc(size_t size)
{
LockGuard lockGuard;

return lockGuard.Locked() ? sys_heap_aligned_alloc(&sHeap, kMallocAlignment, size) : nullptr;
void * const mem = lockGuard.Locked() ? sys_heap_aligned_alloc(&sHeap, kMallocAlignment, size) : nullptr;

#ifdef CONFIG_CHIP_MALLOC_SYS_HEAP_DEBUG
ChipLogProgress(DeviceLayer, "Malloc(%u) = %p, caller: %p", size, mem, __builtin_return_address(0));
#endif

return mem;
}

void * Calloc(size_t num, size_t size)
Expand All @@ -110,7 +116,13 @@ void * Realloc(void * mem, size_t size)
{
LockGuard lockGuard;

return lockGuard.Locked() ? sys_heap_aligned_realloc(&sHeap, mem, kMallocAlignment, size) : nullptr;
void * const new_mem = lockGuard.Locked() ? sys_heap_aligned_realloc(&sHeap, mem, kMallocAlignment, size) : nullptr;

#ifdef CONFIG_CHIP_MALLOC_SYS_HEAP_DEBUG
ChipLogProgress(DeviceLayer, "Realloc(%p, %u) = %p, caller: %p", mem, size, new_mem, __builtin_return_address(0));
#endif

return new_mem;
}

void Free(void * mem)
Expand All @@ -119,6 +131,10 @@ void Free(void * mem)

VerifyOrReturn(lockGuard.Locked());
sys_heap_free(&sHeap, mem);

#ifdef CONFIG_CHIP_MALLOC_SYS_HEAP_DEBUG
ChipLogProgress(DeviceLayer, "Free(%p), caller: %p", mem, __builtin_return_address(0));
#endif
}

#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
Expand Down
Loading