Ulf Axelsson
2005-08-27 21:01:14 UTC
(Note: This is all based on the assumption that LeakAddress currently is
the address of the leaked data, not it's origin as far as I can tell)
I have been thinking some more about how to easily handle registering
expected memory leaks and have come up with the following two variants:
Either
RegisterExpectedMemoryLeak( const aAddress: Cardinal; const aClassName:
String = ''; const aCount: Integer = -1 );
RegisterExpectedMemoryLeak( const aUnit: String; const aLine: Integer;
const aClassName: String = ''; const aCount: Integer = -1 );
In both cases aClassName would be the (optional) name of the class and
aCount the (optional) expected number of leaks. I have chosen to use
aClassName as a String instead of TClass as I assume that a lot of the
expected leaks might be inside implementation blocks in code for which
one do not have source or cannot modify the source, the class type is
not available for those (right?).
Chosing the first version would make it relatively easy to detect if a
leaks is an expected leak. Just walk the stack at the time of the leak
and check if the given address is a return address on it.
Chosing the other version would require the debug info helper (and some
knowledge of it's output format to find the line) before doing the
comparison during the stack walk. But it would be possible to provide a
set of known leaks for each D RTL/VCL version in automatically chosen
include files along with the MM as the "address" no longer is
application dependent.
Unregistering a memory leak should not really be necessary with this
approach.
I hit a small wall on how to implement this though. I assume that the
current code avoids any dynamic allocation for registered leaks because
it does not want to have "private" data mixed with application data and
also avoid all kinds of possible bugs resulting from that? If the number
of leaks get somewhat larger I would need some fast way of checking if
an adress (or unit + lineno) is among the expected leaks. Building a
binary tree in a static array is possible but slightly cumbersome...
I am also not entirely certain on how to find find the stacktrace when
it is time to check for leaks. For example at line 5938 (4.27) the
TFullDebugBlockHeader is stored at the beginning of the LDataPtr block
(?), but is it verified valid at that stage of the check or does that
come later?
An how deep in the stack trace should it be necessary to search? One
would have to step over any references to GetMem etc. but should the
user have to pinpoint the leak exactly or should it be possible to give
an address on a higher level in the call stack?
Comments on all this?
the address of the leaked data, not it's origin as far as I can tell)
I have been thinking some more about how to easily handle registering
expected memory leaks and have come up with the following two variants:
Either
RegisterExpectedMemoryLeak( const aAddress: Cardinal; const aClassName:
String = ''; const aCount: Integer = -1 );
RegisterExpectedMemoryLeak( const aUnit: String; const aLine: Integer;
const aClassName: String = ''; const aCount: Integer = -1 );
In both cases aClassName would be the (optional) name of the class and
aCount the (optional) expected number of leaks. I have chosen to use
aClassName as a String instead of TClass as I assume that a lot of the
expected leaks might be inside implementation blocks in code for which
one do not have source or cannot modify the source, the class type is
not available for those (right?).
Chosing the first version would make it relatively easy to detect if a
leaks is an expected leak. Just walk the stack at the time of the leak
and check if the given address is a return address on it.
Chosing the other version would require the debug info helper (and some
knowledge of it's output format to find the line) before doing the
comparison during the stack walk. But it would be possible to provide a
set of known leaks for each D RTL/VCL version in automatically chosen
include files along with the MM as the "address" no longer is
application dependent.
Unregistering a memory leak should not really be necessary with this
approach.
I hit a small wall on how to implement this though. I assume that the
current code avoids any dynamic allocation for registered leaks because
it does not want to have "private" data mixed with application data and
also avoid all kinds of possible bugs resulting from that? If the number
of leaks get somewhat larger I would need some fast way of checking if
an adress (or unit + lineno) is among the expected leaks. Building a
binary tree in a static array is possible but slightly cumbersome...
I am also not entirely certain on how to find find the stacktrace when
it is time to check for leaks. For example at line 5938 (4.27) the
TFullDebugBlockHeader is stored at the beginning of the LDataPtr block
(?), but is it verified valid at that stage of the check or does that
come later?
An how deep in the stack trace should it be necessary to search? One
would have to step over any references to GetMem etc. but should the
user have to pinpoint the leak exactly or should it be possible to give
an address on a higher level in the call stack?
Comments on all this?