関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。
ここ最近、unsafeパッケージについてのメモをちょこちょこしているので、ついでなので unsafe パッケージの他の関数についてもメモ残しておこうと思いました。
今回は、構造体のメモリレイアウトを見るについて。
面白いのが、パディングが入るように構造体を定義して、それをダンプしてみるとパディング部分にゴミが見える点です。
Goの仕様では、構造体のフィールドは初期化されますが、アライメントのためのパディング領域は未定義です。(言語仕様に記載が無い)
なので、実行するたびに変な値が見えたりします。まあ、パディングのエリアは値何でも良いので挙動に何も影響は及びません。
サンプル
unsafe_dump.go
package unsafes import ( "encoding/hex" "fmt" "math" "os" "unsafe" ) // Dump は、unsafeパッケージを使って構造体のメモリダンプを出力するサンプルです。 func Dump() error { type ( // わざとパディングが入る構造体とする // size: 24bytes S1 struct { A uint8 // offset=0, size=1, padding=3 B uint32 // offset=4, size=4, padding=0 C uint64 // offset=8, size=8, padding=0 D uint16 // offset=16, size=2, padding=6 } ) // 構造体のメモリダンプ // 尚、実行すると以下のように // 00000000 ff 62 a6 00 ff ff ff ff ff ff ff ff ff ff ff ff // 00000010 ff ff 1e 00 c0 00 00 00 // 62 a6 のようなゴミが見える。これはGoはパディング部分をゼロ初期化しないため。 // Goの仕様では、構造体のフィールドは初期化されるが、アライメントのためのパディング領域は未定義となっている。 var ( s1 = S1{math.MaxUint8, math.MaxUint32, math.MaxUint64, math.MaxUint16} size = unsafe.Sizeof(s1) ptr = unsafe.Pointer(&s1) bytePtr = (*byte)(ptr) byteSlice = (([]byte)(unsafe.Slice(bytePtr, size))) ) hex.Dumper(os.Stdout).Write(byteSlice) fmt.Println("") // ゼロクリアしてから値を再設定して確認してみる // 以下のループはmemset(ptr, 0, size) と同じ感じ。 for i := range int(size) { if i == 0 { *bytePtr = 0 } ptr = unsafe.Add(ptr, 1) bytePtr = (*byte)(ptr) *bytePtr = 0 } // 構造体の値を設定しなおし s1.A = math.MaxUint8 s1.B = math.MaxUint32 s1.C = math.MaxUint64 s1.D = math.MaxUint16 hex.Dumper(os.Stdout).Write(byteSlice) return nil }
実行
$ task
task: [build] go build -o "/home/dev/dev/github/try-golang/try-golang" .
task: [run] ./try-golang -onetime
ENTER EXAMPLE NAME: unsafe_dump
[Name] "unsafe_dump"
00000000 ff 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000010 ff ff 18 00 c0 00 00 00
00000000 ff 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000010 ff ff 00 00 00 00 00 00
[Elapsed] 88.436µs
参考情報
個人的Goのおすすめ書籍
個人的に読んでとても勉強になった書籍さんたちです。
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。






