mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-25 22:03:45 -06:00
Fixed reporting leaks for GLCtrl in Linux with Radeon driver, new memory leaks detection related functions.
This commit is contained in:
parent
38b6807ff4
commit
d8d16229d1
9 changed files with 110 additions and 10 deletions
|
|
@ -440,10 +440,15 @@ void Exit(int code)
|
|||
throw ExitExc();
|
||||
}
|
||||
|
||||
void MemorySetMainBegin__();
|
||||
void MemorySetMainEnd__();
|
||||
|
||||
void AppExecute__(void (*app)())
|
||||
{
|
||||
try {
|
||||
MemorySetMainBegin__();
|
||||
(*app)();
|
||||
MemorySetMainEnd__();
|
||||
}
|
||||
catch(ExitExc) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -170,6 +170,11 @@ inline void TinyFree(int, void *ptr) { return MemoryFree(ptr); }
|
|||
|
||||
#endif
|
||||
|
||||
dword MemoryGetCurrentSerial();
|
||||
|
||||
void MemoryIgnoreNonMainLeaks();
|
||||
void MemoryIgnoreNonUppThreadsLeaks();
|
||||
|
||||
struct MemoryIgnoreLeaksBlock {
|
||||
MemoryIgnoreLeaksBlock() { MemoryIgnoreLeaksBegin(); }
|
||||
~MemoryIgnoreLeaksBlock() { MemoryIgnoreLeaksEnd(); }
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ struct sThreadParam {
|
|||
bool noshutdown;
|
||||
};
|
||||
|
||||
static thread_local bool sUppThread = false;
|
||||
|
||||
static
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifdef CPU_64
|
||||
|
|
@ -82,6 +84,7 @@ static
|
|||
sThreadRoutine(void *arg)
|
||||
{
|
||||
LLOG("sThreadRoutine");
|
||||
sUppThread = true;
|
||||
auto p = (sThreadParam *)arg;
|
||||
try {
|
||||
p->cb();
|
||||
|
|
@ -191,6 +194,11 @@ Thread::~Thread()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool Thread::IsUpp()
|
||||
{
|
||||
return sUppThread;
|
||||
}
|
||||
|
||||
bool Thread::IsST() //the containing thread (of wich there may be multiple) has not run its Run() yet
|
||||
{
|
||||
return !threadr;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public:
|
|||
|
||||
static bool IsST();
|
||||
static bool IsMain();
|
||||
static bool IsUpp();
|
||||
static int GetCount();
|
||||
static void BeginShutdownThreads();
|
||||
static void EndShutdownThreads();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,39 @@
|
|||
|
||||
// #define LOGAF
|
||||
|
||||
namespace Upp {
|
||||
|
||||
static bool sIgnoreNonMainLeaks;
|
||||
static bool sIgnoreNonUppThreadsLeaks;
|
||||
|
||||
static dword serial_number = 0;
|
||||
static dword serial_main_begin;
|
||||
static dword serial_main_end;
|
||||
|
||||
dword MemoryGetCurrentSerial() { return serial_number; }
|
||||
|
||||
void MemoryIgnoreNonMainLeaks()
|
||||
{ // ignore leaks outside _APP_MAIN
|
||||
sIgnoreNonMainLeaks = true;
|
||||
}
|
||||
|
||||
void MemoryIgnoreNonUppThreadsLeaks()
|
||||
{ // ignore leaks in threads not launched by U++ Thread
|
||||
sIgnoreNonUppThreadsLeaks = true;
|
||||
}
|
||||
|
||||
void MemorySetMainBegin__()
|
||||
{
|
||||
serial_main_begin = serial_number;
|
||||
}
|
||||
|
||||
void MemorySetMainEnd__()
|
||||
{
|
||||
serial_main_end = serial_number;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if (defined(TESTLEAKS) || defined(HEAPDBG)) && defined(COMPILER_GCC) && defined(UPP_HEAP)
|
||||
|
||||
int sMemDiagInitCount;
|
||||
|
|
@ -85,12 +118,14 @@ void *MemoryAllocSz_(size_t& size);
|
|||
|
||||
void DbgSet(DbgBlkHeader *p, size_t size)
|
||||
{
|
||||
static dword serial_number = 0;
|
||||
bool allow_leak = s_ignoreleaks ||
|
||||
sIgnoreNonUppThreadsLeaks && !Thread::IsUpp() && !Thread::IsMain()
|
||||
#if (defined(TESTLEAKS) || defined(HEAPDBG)) && defined(COMPILER_GCC) && defined(UPP_HEAP)
|
||||
p->serial = sMemDiagInitCount == 0 || s_ignoreleaks ? 0 : ~ ++serial_number ^ (dword)(uintptr_t) p;
|
||||
#else
|
||||
p->serial = s_ignoreleaks ? 0 : ~ ++serial_number ^ (dword)(uintptr_t) p;
|
||||
|| sMemDiagInitCount == 0
|
||||
#endif
|
||||
;
|
||||
|
||||
p->serial = allow_leak ? 0 : ~ ++serial_number ^ (dword)(uintptr_t) p;
|
||||
p->size = size;
|
||||
if(s_allocbreakpoint && s_allocbreakpoint == serial_number)
|
||||
__BREAK__;
|
||||
|
|
@ -209,7 +244,8 @@ void MemoryDumpLeaks()
|
|||
bool leaks = false;
|
||||
int n = 0;
|
||||
while(p != &dbg_live) {
|
||||
if(p->serial) {
|
||||
dword serial = (unsigned int)~(p->serial ^ (uintptr_t)p);
|
||||
if(p->serial && (!sIgnoreNonMainLeaks || serial >= serial_main_begin && serial < serial_main_end)) {
|
||||
if(!leaks)
|
||||
VppLog() << "\n\nHeap leaks detected:\n";
|
||||
leaks = true;
|
||||
|
|
@ -222,7 +258,6 @@ void MemoryDumpLeaks()
|
|||
++n;
|
||||
p = p->next;
|
||||
}
|
||||
sprintf(b, "%d", n);
|
||||
VppLog() << "\n*** TOO MANY LEAKS (" << n << ") TO LIST THEM ALL\n";
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ is slightly faster.&]
|
|||
[s2;%% Attempts to change the size of block at [%-*@3 ptr] to something
|
||||
closer to [%-*@3 newsize]. The real value is returned in [%-*@3 newsize].
|
||||
Returns true on success.&]
|
||||
[s3;%% &]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:TinyAlloc`(int`): [@(0.0.255) void]_`*[* TinyAlloc]([@(0.0.255) int]_[*@3 size])&]
|
||||
[s2;%% Allocates the block of [%-*@3 size] bytes. This allows for allocation
|
||||
|
|
@ -76,7 +76,7 @@ TinyFree.&]
|
|||
e], [@(0.0.255) void]_`*[*@3 ptr])&]
|
||||
[s2;%% Frees the block allocated with TinyAlloc, [%-*@3 size] has to
|
||||
be the same as during allocation.&]
|
||||
[s3;%% &]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:tiny`_new`(Args`.`.`.args`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T],
|
||||
[@(0.0.255) class...]_[*@4 Args]>_[*@4 T]_`*[* tiny`_new]([*@4 Args][@(0.0.255) ...]_args)&]
|
||||
|
|
@ -122,6 +122,43 @@ b])&]
|
|||
[s2;%% This debug / diagnostics function limits memory usage to [%-*@3 kb]
|
||||
KBs. If the application allocates more, it stops with error.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:MemoryGetCurrentSerial`(`): [_^Upp`:`:dword^ dword]_[* MemoryGetCurrentSerial
|
||||
]()&]
|
||||
[s2;%% In debug mode, returns the serial number of the next allocated
|
||||
block. This number is eventually listed in the log in case there
|
||||
are any leaks.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:MemoryIgnoreNonMainLeaks`(`): [@(0.0.255) void]_[* MemoryIgnoreNonMainLeaks](
|
||||
)&]
|
||||
[s2;%% Makes leaks detector ignore leaks by global constructors.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:MemoryIgnoreNonUppThreadsLeaks`(`): [@(0.0.255) void]_[* MemoryIgnoreNonUppTh
|
||||
readsLeaks]()&]
|
||||
[s2;%% Makes leaks dectector ignore leaks created by threads that
|
||||
are not launched by U`+`+ Thread class.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:MemoryIgnoreLeaksBegin`(`): [@(0.0.255) void]_[* MemoryIgnoreLeaksBegin]()&]
|
||||
[s2;%% Makes leak detector ignore leaks of blocks allocated until
|
||||
[%-* MemoryIgnoreLeaksEnd ]is called. Calls can be nested. This
|
||||
is especially useful when working with 3rd party code that might
|
||||
e.g. create static leaks (memory is allocated just once, but
|
||||
library does not bother to deallocate on exit).&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:MemoryIgnoreLeaksEnd`(`): [@(0.0.255) void]_[* MemoryIgnoreLeaksEnd]()&]
|
||||
[s2;%% Ends the suppression started by MemoryIgnoreLeaksBegin.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s1;:Upp`:`:MemoryIgnoreLeaksBlock`:`:struct: [@(0.0.255) struct]_[* MemoryIgnoreLeaksBlo
|
||||
ck]&]
|
||||
[s2;%% This helper class calls [%-* MemoryIgnoreLeaksBegin] in constructor
|
||||
and [%-* MemoryIgnoreLeaksEnd], in other works supresses leaks
|
||||
till the end of block.&]
|
||||
[s3;%% &]
|
||||
[ {{10000F(128)G(128)@1 [s0;%% [* Heap tuning]]}}&]
|
||||
[s0;%% &]
|
||||
[s0;%% Heap tuning is provided through MemoryOptions class. Constructor
|
||||
|
|
|
|||
|
|
@ -91,14 +91,19 @@ t]_[*@3 ms])&]
|
|||
[s3;%- &]
|
||||
[s4;%- &]
|
||||
[s5;:Thread`:`:IsST`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsST]()&]
|
||||
[s2; No additional thread was started yet (only the main thread is
|
||||
running so far).&]
|
||||
[s2; No additional U`+`+ Thread was started yet (only the main thread
|
||||
is running so far).&]
|
||||
[s3;%- &]
|
||||
[s4;%- &]
|
||||
[s5;:Thread`:`:IsMain`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsMain]()&]
|
||||
[s2; Returns true if current thread is main.&]
|
||||
[s3;%- &]
|
||||
[s4;%- &]
|
||||
[s5;:Upp`:`:Thread`:`:IsUpp`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsUpp]()&]
|
||||
[s2; Calling thread was started using U`+`+ Thread class (for main
|
||||
thread returns false).&]
|
||||
[s3;%- &]
|
||||
[s4;%- &]
|
||||
[s5;:Thread`:`:GetCount`(`):%- [@(0.0.255) static] [@(0.0.255) int]_[* GetCount]()&]
|
||||
[s2; Number of running threads (started using Thread class).&]
|
||||
[s3;%- &]
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ void GLCtrl::Init()
|
|||
Add(pane.SizePos());
|
||||
#endif
|
||||
restore_gl_viewport__ = SetCurrentViewport;
|
||||
MemoryIgnoreNonMainLeaks();
|
||||
MemoryIgnoreNonUppThreadsLeaks(); // Linux drivers leak memory in threads
|
||||
}
|
||||
|
||||
Image GLCtrl::MouseEvent(int event, Point p, int zdelta, dword keyflags)
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ void GLCtrl::Create()
|
|||
|
||||
void GLCtrl::Sync()
|
||||
{
|
||||
MemoryIgnoreLeaksBlock __;
|
||||
|
||||
if(win) {
|
||||
Rect r = GetScreenView() - GetTopCtrl()->GetScreenRect().TopLeft();
|
||||
bool b = IsVisible() && r.GetWidth() > 0 && r.GetHeight() > 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue