Linux memory leakage detection (4) record the leak size

Source: Internet
Author: User

Linux memory leakage detection (4) record the leak size

Linux memory leakage detection (3) Customized new/delete: using the feature of C ++ function overloading, make C ++ code, you can also easily add Statistical Code for new/delete to detect memory leaks. However, new problems are introduced as well.

The current statistical method only counts the number of times the memory is applied for/released, and does not count the size of each applied/released memory.
This method is enough for C, because the size of the application and release in C is the same, and it is not necessarily in C ++.
Consider the following two situations:

(1) only the space of the parent class is released when the subclass space is applied.

father *pF = new son;delete pF;

When constructing a subclass, the requested space is the size required by the subclass. Then, the parent class members are initialized before the child class members are initialized.

During the analysis, the pointer of the parent class only calls the destructor of the parent class and releases the space occupied by the parent class.
Isn't it polymorphism? Since the pF pointer subclass does not call the destructor of the subclass?
Because the premise of polymorphism is virtual functions.

Under normal circumstances, class destructor should all be written as virtual functions. If you forget it, it may cause memory leakage.

(2) apply for an array space, but only release the space of the first element

class A *pA = new class[5];delete pA;

Not all of these cases will cause memory leakage. If the class is of a built-in type, such as int or char, there is no problem. For the built-in type, we can only say that there is no memory leakage, but there may be other unknown potential problems, so we do not recommend this writing.
In C ++, the class is not limited to the built-in type. If it is a defined class, delete pA only releases the first entry of the array pointed to by pA, in this way, memory leakage occurs.

For the above reason, only the number of application/release times is counted, and the memory leakage cannot be accurately detected. Therefore, the size must be recorded at the same time of application/release.

Have you ever asked this question when writing code? Why do I need to input the size of the memory to be applied for when applying for the memory?

This is because the applied size is recorded in a specific place during the application, and the size is determined from the corresponding recipient during the release. So what do you remember?

There are two methods:

1. Non-Intrusive, the memory distributor first applies for memory (used with the stack) and is used to record the application records (addresses, sizes) at the user layer ). The table is searched for when the user releases the space. In addition to knowing the size of the space to be released, the pointer can also be determined to be legal.

2. For example, if you want to apply for 1 byte memory, the memory distributor allocates 5 bytes of space (32 bits). The first 4 bytes are used for the requested size. When the memory is released, the request size is first offset by four bytes before the request is released.

The two methods have their own advantages and disadvantages. The first method is secure but slow. The second approach is fast, but it requires a higher level of pointer control capability for programmers. A slight carelessness that crosses the border may damage space information.

The gcc/g ++ compiler on linux uses the intrusion type by default. to verify whether the address we found stores the data we want, I wrote the test code as follows:

#include 
  
   using namespace std;#if(defined(_X86_) && !defined(__x86_64))#define _ALLOCA_S_MARKER_SIZE 4#elif defined(__ia64__) || defined(__x86_64)#define _ALLOCA_S_MARKER_SIZE 8#endifint main(void){    void * p = NULL;    int a = 5, n = 1;    while (a--)    {        p = new char[n];        size_t w = *((size_t*)((char*)p -  _ALLOCA_S_MARKER_SIZE));        cout<<"w = "<< w <<" n = "<
   
  

Here is the running result:

w = 33 n = 1

w = 33 n = 10

w = 113 n = 100

w = 1009 n = 1000

w = 10017 n = 10000

When we read the first few bytes of the applied memory, the data we found seems to be related to the actual applied data, but it is always slightly larger. Is this the data we are looking? What is the relationship between it and the actual application size? This should begin with the memory allocation policy of gcc.

Assume that the size of the requested space is n and the actual size of the allocated space is m. The read value is k.

(1) When you call malloc to apply for n spaces, the compiler will allocate more _ ALLOCA_S_MARKER_SIZE bytes to store the management information of the space. On the centos 64 I tested, this management information is a total of 8 bytes, and the size of the requested space mentioned above is in it. Then m = n + _ ALLOCA_S_MARKER_SIZE

(2) In order to reduce the memory fragmentation, the requested size is an integer multiple of the number. On the centos 64 I tested, this number is measured as 16, that is, the actual application size is a multiple of 16. Then m = (n + 8-1) & 0xFFFFFFF0 + 0x10

(3) to avoid applying for too small memory, the minimum actual allocated space is 0x20.
M = (n + 8-1) & 0xFFFFFFF0 + 0x10 if m <0x20 m = 0x20

(4) Because m must be a multiple of 16, the last four bits of m in binary are always 0, which does not work. Therefore, these four bits are used as standard bits. So k = m + 1

Conclusion m = (n + 7) & 0xFFFFFFF0 + 0x11, k = m + 1

To prove this conclusion is correct, I wrote the following code:

#include  using namespace std;#include#include  #include  #if(defined(_X86_) && !defined(__x86_64))#define _ALLOCA_S_MARKER_SIZE 4#elif defined(__ia64__) || defined(__x86_64)#define _ALLOCA_S_MARKER_SIZE 8#endifint main(void){ void * p = NULL; srand(time(0)); int a = 100000; while (a--) { int n = rand() % 10000; p = new char[n]; size_t w = *((size_t*)((char*)p - _ALLOCA_S_MARKER_SIZE)); if ( n <= 8) n = 9; int n2 = ((n+7) & 0xFFFFFFF0) + 0x11; assert(n2 == w); } return 0;}   

In fact, we do not care about the caller's application size during statistics, but the size of the compiler's real application and release, that is, the Code is as follows:

#include  using namespace std;#include  #include  #if(defined(_X86_) && !defined(__x86_64))#define _ALLOCA_S_MARKER_SIZE 4#elif defined(__ia64__) || defined(__x86_64)#define _ALLOCA_S_MARKER_SIZE 8#endifsize_t count = 0;extern "C"{void* __real_malloc(int c); void * __wrap_malloc(int size){ void *p = __real_malloc(size); size_t w = *((size_t*)((char*)p - _ALLOCA_S_MARKER_SIZE)) - 1; count += w; cout<<"malloc "<    

Now we will test the two cases mentioned above:

(1) only the space of the parent class is released when the subclass space is applied.

class father{ int *p1;public: father(){p1 = new int;} ~father(){delete p1;}};class son : public father{ int *p2;public: son(){p2 = new int;} ~son(){delete p2;}};int main(void){ count = 0; father *p = new son; delete p; if(count != 0) cout<<"memory leak!"< 

(2) apply for an array space, but only release the space of the first element

class A{ int *p1;public: A(){p1 = new int;} ~A(){delete p1;}};int main(void){ count = 0; A *p = new A[5]; delete p; if(count != 0) cout<<"memory leak!"< 

Analysis:

Convenience:
Function Supported? Description
Runtime check No This method requires that the printed analysis results generated during the running end of the running process be known.
Convenient Modification Yes The wrap function is easy to implement and only needs to be implemented once. It is effective for all files involved in the link.
Convenient to use Yes To disable this function, you only need to remove this link option.

-Comprehensiveness:

Function Supported? Description
Can C interfaces be processed in a unified manner? No Each interface of C needs to write the packaging function separately.
Can C ++ interfaces be processed in a unified manner? Yes  
Can memory leakage of dynamic and static databases be detected? Yes Wrap is a link option.__wrap_mallocAnd__wrap_freeAll files linked together work, whether it is. o,. a, or. so.

-Accuracy:

Function Supported? Description
Is there a situation that cannot be detected? No  
Can the row be located? No  
Determines the size of the leaked Space Yes  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.