Who moved my pointer?

Source: Internet
Author: User

Who moved my pointer?

Preface:
This article introduces a method for finding a hanging pointer (wild pointer) in the debugging process. This method is implemented by reloading the new and delete operators.
This method is not perfect. It is implemented at the cost of Memory leakage during the debugging period, because the code displayed in this article cannot appear in a final software product, it can only be used during debugging.
In VC, In the debugging environment, you can simply replace new with debug_new to implement more powerful and convenient pointer detection. For details, refer to msdn. The implementation idea of debug_new is similar to that in this article. Therefore, although the method described in this article is not the best, it is still practical and, more importantly, it provides us with a new idea.

Introduction:
A few days ago, this happened. I was debugging a program. This program used a bunch of messy pointers to process a linked list and eventually encountered a problem on a pointer pointing to the linked list node. We expect it to point to a virtual base class object. I thought of the first question: Is there an object in the pointer? The problematic pointer value can be divisible by 4 and is not null, so it can be determined that it was a valid pointer. By using the Visual Studio memory display window (View-> debug windows-> memory), we found that the data indicated by this pointer is Fe EE Fe Ee... this usually means that the memory is previously allocated, but is now in an unallocated state. I don't know who it is and where it is. I have released the memory area pointed by my pointer. I want to find a solution to find out how my data is released.

Background:
I finally found my lost data by reloading the new and delete operators. When a function is called, the parameter is first pressed to the stack, and then the return address is also pressed to the stack. We can extract the information from the stack in the functions of the new and delete operators to help us debug the program.

Code:
After several false guesses, I decided to resort to the new and delete operators to help me find the data pointed to by my pointer. The implementation of the new operator below extracts the return address from the stack. The returned address is located between the passed parameter and the address of the first local variable. The compiler settings, function calling methods, and computer architecture all sound to the actual location of the returned address. Therefore, when you use the following code, make some adjustments based on your actual situation. Once the new operator obtains the return address, it allocates an additional 16 bytes before the memory to be actually allocated to store the return address and the actually allocated memory size, return the first address of the memory block to be allocated.
For the delete operator, you can see that it no longer releases space. It extracts the returned address in the same way as new and writes it to the end of the actually allocated space (Note: It is 9th to 12th bytes of the 16 bytes allocated above ), in the last four bytes, enter de ad be ef (Note: The four hexadecimal numbers are exactly the dead beef words used to indicate that the memory has been released !), And fill in the remaining space (the space that should be actually allocated but should be released now) with a duplicate value.
Now, if the program fails due to a wrong pointer, I just need to open the memory View window, find the location indicated by the wrong pointer, and then look for 16 bytes. The value here is the address for calling the new operator. The next four bytes are the actually allocated memory size, and the third four bytes are the addresses for calling the delete operator, the last four bytes should be De ad be EF. The next actually allocated memory should be 77 77 77 77.
You need to find the corresponding new and delete addresses in the source program. You can do this: first, sort the four bytes of the address in reverse order, in this way, we can get the real address, because the byte order on the Intel Platform is low. Next, right-click the source code and select "go to diassembly ". The left column of the Disassembly window is the memory address corresponding to the machine code. Press Ctrl + G or select edit-> go to... and enter one of the addresses you have found. The Disassembly window will scroll to the corresponding new or delete function call location. To return to the source program, right-click again and select "go to source ". You can see the corresponding new or delete call.
Now you can easily find out when your data is lost. It depends on you to find out why delete is called.
# Include <malloc. h>

Void *: Operator new (size_t size)
{
Int stackvar;
Unsigned long stackvaraddr = (unsigned long) & stackvar;
Unsigned long argaddr = (unsigned long) & size;

Void ** retaddraddr = (void **) (stackvaraddr/2 + argaddr/2 + 2 );

Void * retaddr = * retaddraddr;

Unsigned char * retbuffer = (unsigned char *) malloc (size + 16 );

Memset (retbuffer, 0, 16 );

Memcpy (retbuffer, & retaddr, sizeof (retaddr ));

Memcpy (retbuffer + 4, & size, sizeof (size ));

Return retbuffer + 16;
}

Void: Operator Delete (void * BUF)
{
Int stackvar;
If (! Buf)
Return;

Unsigned long stackvaraddr = (unsigned long) & stackvar;
Unsigned long argaddr = (unsigned long) & Buf;

Void ** retaddraddr = (void **) (stackvaraddr/2 + argaddr/2 + 2 );

Void * retaddr = * retaddraddr;

Unsigned char * buf2 = (unsigned char *) BUF;

Buf2-= 8;

Memcpy (buf2, & retaddr, sizeof (retaddr ));

Size_t size;

Buf2-= 4;

Memcpy (& size, buf2, sizeof (buf2 ));

Buf2 + = 8;

Buf2 [0] = 0xde;
Buf2 [1] = 0xad;
Buf2 [2] = 0xbe;
Buf2 [3] = 0xef;

    
Buf2 + = 4;

Memset (buf2, 0x7777, size );

// Deallocating destroys saved addresses, so don't
// Buf-= 16;
// Free (BUF );
}

Other important points:
This code can also be used for Memory leakage detection. You only need to modify the delete operator so that it can actually release the memory. before exiting the program, use _ heapwalk to traverse all allocated memory blocks and extract the new address, this generates a new call list that is not matched by the delete operation.
Note that the Code listed here can only be used during debugging. If you put the code segment into the final product, the memory will be greatly consumed during program running.

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.