laitimes

Learn about Delve's memory viewing capabilities

author:Flash Gene

01

What is Delve

Learn about Delve's memory viewing capabilities
Learn about Delve's memory viewing capabilities

Delve is a Golang debugging tool, which can provide breakpoint debugging functions, view the current data, and even switch to different coroutines to view the data, most IDEs have been integrated.

Using the above features, it is actually very convenient to debug Go programs, but its functions are more than that, so let's take a look at one of the features that is helpful for understanding the Go language: memory viewing.

02

Program memory

Learn about Delve's memory viewing capabilities
Learn about Delve's memory viewing capabilities

When the program is running, it is loaded from the hard disk into memory, which looks like this

Learn about Delve's memory viewing capabilities

Among them, the code of the program is compiled into machine code, and there is a program code area, in addition to this, the most important thing should be the stack and heap.

The address space of the stack grows from high to low, and the memory of the heap generally grows upward, but due to the memory manager that comes with the Go language and the existence of coroutines, the actual memory address obtained may not be exactly according to the general situation.

For the next content, you need to close the endian, the endianism is generally big-endian storage or small-endian storage, the data stored in the big endian is stored in the low address bit of memory, and the data stored in the small endian is stored in the high address bit of memory.

Linux systems can view the Byte Order field through lscpu, and most Intel and AMD CPUs should be Little Endian.

This means that, assuming that a pointer points to an address that is 0xc0123456, the pointer variable should hold a value of 0x56 0x34 0x12 0xc0 from the low address to the high address (4 bytes are used here for simplicity, when in fact the pointer variable on a 64-bit system should occupy 8 bytes)

03

How to use:

Learn about Delve's memory viewing capabilities
Learn about Delve's memory viewing capabilities
Learn about Delve's memory viewing capabilities

After installing Delve, you can use Delve to debug the file where the main function is located, such as dlv debug main.go, which will go to the command line of delve.

You can then use b main.go:9 to set a breakpoint on line 9, as shown in the image below

Learn about Delve's memory viewing capabilities

At this point, you can see that the DLV provides an address, and a breakpoint is added here, and when the program runs to the address where the program is located, it will be paused.

You can go in now and see what's at this address. Since we already know that this place is the address of the program code block, we need to use the decompilation method here to convert the machine code in memory into assembly language, and this is also one of Delve's functions

Run: disass -a 0x495c75 0x495d75, start from this address, 0x100 bytes back, decompile it, you can get a result like this (not truncated)

Learn about Delve's memory viewing capabilities

This is the assembly code (part) that calls println in the main function

Now continue to type c, Delve will run to the next breakpoint, which is before println, and here you can see some data for the two variables a and b

You can use the p command to obtain the value of the corresponding variable, such as p a or p b

Learn about Delve's memory viewing capabilities

This is exactly the value set in the code, and you can see the corresponding address by using p &a and p &b

Learn about Delve's memory viewing capabilities

Here we get the addresses of the two variables, and then you can use Delve's method of outputting the raw data of the memory to see what these two addresses store

Use x -fmt hex -len 32 0xc00010cef0, where x means the output raw data, -fmt hex means it has been formatted in a 1xadecimal format, -len 32 means the output is 32 bytes after the specified address, and then you can get something like that

Learn about Delve's memory viewing capabilities

Since the int type occupies 8 bytes on a 64-bit system, it can go up to 8 bytes after the start of the memory where a is located, and it is actually a variable, and it is 1.

The last 3 lines, for the developer, don't know who it belongs to or what it means, because the memory is maintained by Golang.

Again, look at where B is located

Learn about Delve's memory viewing capabilities

The first 8 bytes here are obviously not abc, and the last 8 bytes are exactly 3, that is, the length of the string, which is exactly in line with Golang's knowledge: a string is a string of addresses and lengths that point to the first address of continuous memory.

So the first 8 bytes should be an address, so track the past again

Learn about Delve's memory viewing capabilities

In this way, I found that the 3 bytes on the address are exactly the value corresponding to the ABC of ASCII, and since the code just now is written in UTF8, and UTF8, as a variable-length character encoding format, is compatible with ASCII, so ABC is exactly 0x61 0x62 0x63 under UTF8.

And since the length seen above is 3, only the first 3 bytes can be read, and the following bytes still don't know what they mean.

04

summary

Learn about Delve's memory viewing capabilities
Learn about Delve's memory viewing capabilities

A simple example of Delve's memory viewing feature can help you understand Golang's data structure and provide a reference for optimizing code speed.

For example, in the example above, it is shown that the string exists in continuous memory, and the memory behind its length is unknown data, so that is, if I want to append a character to the string, I can't overwrite the original data directly after the original memory.

At this point, Golang has to open up a new memory that is large enough, copy the current string, and finally write the characters that need to be appended. GC needs to be considered to open up memory, and replication will take time.

Therefore, when concatenating strings in a loop, you need to consider whether multiple GCs will affect the execution efficiency.

Author: Qiu Cheng

Source-WeChat public account: Sanqi Mutual Entertainment Technical Team

Source: https://mp.weixin.qq.com/s/svedLIwIzbwtEEsO7kJqAQ

Read on