Backend Development 27 min read

Analyzing Go Memory Layout and Object Dumping

The article demonstrates how to examine a running Go program’s memory layout by defining example structs, using unsafe.Sizeof/Alignof, dumping writable regions via a Bash script and GDB, and locating fields and string constants in the resulting memory dumps to verify object representation.

Tencent Cloud Developer
Tencent Cloud Developer
Tencent Cloud Developer
Analyzing Go Memory Layout and Object Dumping

When handling memory leaks, the author explores how to inspect objects in a running Go program by visualizing its memory layout.

Before the analysis, basic Go memory concepts are introduced: memory alignment, struct size, and the fact that heap objects do not carry type information. The internal representation of a string is shown as a struct with a Data pointer and a Len field, and a slice (array) is represented by a struct with Data , Len , and Cap fields.

Two example structs are defined:

type User struct {
    Name  string
    Age   uint8
    Sex   uint8
    class *Class
}

type Class struct {
    CName string
    Index uint
}

Using unsafe.Sizeof and unsafe.Alignof , the memory layout of Class (24 bytes) and User (32 bytes) is printed, with a diagram of the byte ranges for each field.

A small Go program creates an instance of User , fills the fields, and runs indefinitely, allowing the process memory to be examined. The program also prints the PID.

package main

import (
    "fmt"
    "math/rand"
    "os"
    "os/signal"
    "strconv"
)

var user *User

func main() {
    idx := rand.Intn(10)
    user = &User{
        Name: "zhangsan",
        Age:  18,
        Sex:  1,
        class: &Class{
            CName: "class-" + strconv.Itoa(idx),
            Index: uint(idx),
        },
    }
    fmt.Println(user)
    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, os.Kill)
    s := <-c
    fmt.Println("receive signal -> ", s)
}

To dump the memory of the running process, a Bash script dump-all-mem.sh reads /proc/$1/maps , filters writable regions, and invokes gdb --batch --pid $1 -ex "dump memory …" for each region, producing a set of .dump files.

#!/bin/bash

grep rw-p /proc/$1/maps | while read start stop; do
    gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"
    done

The resulting dump files are inspected with strings to locate the unique marker class- , and with hexdump -c to view the raw bytes. By calculating the offset of the marker within the dump (e.g., 00ae010 ), the absolute address c0000ae010 is derived.

Further analysis matches the bytes to the expected layout of Class (pointer, length, index) and User (name pointer, length, age, sex, padding, class pointer). The author verifies that the values printed by the program (Age=18, Sex=1, Name length=8) correspond to the bytes observed in the dump.

Finally, the location of the string "zhangsan" is found in the read‑only segment ( r--p ) of the process memory, confirming that constant strings reside in a non‑writable, non‑executable region.

The article concludes with references to Linux /proc/<pid>/maps analysis and Go memory inspection techniques.

debuggingGolinuxmemory layoutHeap Inspectionstruct
Tencent Cloud Developer
Written by

Tencent Cloud Developer

Official Tencent Cloud community account that brings together developers, shares practical tech insights, and fosters an influential tech exchange community.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.