質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

1回答

3167閲覧

Goでメモリを16進ダンプする上手い実装方法は?

kppn

総合スコア44

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2015/04/27 15:28

編集2015/12/11 02:32

GOを学習中のものです。
ポインターからメモリ内容をリニアに出力する方法を探しています。

unsafe.Pointerを経由して長大なByte配列へのポインタへ変換(Conversion)し、
必要分だけ打ち出す実装を試したところ、当面の目的は達成しました。
しかし、この「長大なByte配列へのポインタ」というやり方に不安を覚えています。
・処理系依存とならないか。
・ヒープを不要に確保してしまわないか
C/C++のように、ポインタ演算で型チェックが行われない、純粋なポインタとして扱う
方法があればご紹介頂けないでしょうか。

以下はスライスの内容をその参照先の配列も含め出力する処理を試したものです。

lang

1func dump(up unsafe.Pointer, n uintptr) { 2 p := (*[4294967296]byte)(up) 3 4 uip := uintptr(up) 5 for i := 0; i < (int)(n); i++ { 6 if (i % 16 == 0) { 7 fmt.Printf("%x : ", uip + (uintptr)(i)); 8 } 9 10 fmt.Printf("%02x", p[i]) 11 12 if (i % 4 == 3) { 13 fmt.Printf(" ") 14 } 15 if (i % 16 == 15) { 16 fmt.Printf("\n") 17 } 18 } 19 fmt.Printf("\n") 20} 21 22func dumpSliceInt(sl *[]int) { 23 // スライスオブジェクト部を出力 24 fmt.Printf("---- slice object ----\n") 25 dump(unsafe.Pointer(sl), unsafe.Sizeof(*sl)) 26 27 28 // スライスオブジェクト中の配列へのポインタを*[1]Intへ無理矢理変換し 29 // 配列部へのポインタを得る. Intのサイズとポインターのサイズが同じで 30 // 無ければ動く保障は無い(?) 31 up := unsafe.Pointer(sl) 32 ip := (*[1](*int))(up) 33 34 // 配列部を出力 35 fmt.Printf("---- sliced array ----\n") 36 dump(unsafe.Pointer(ip[0]), (uintptr)(cap(*sl)) * unsafe.Sizeof((*sl)[0])) 37} 38 39func main() { 40 sl1 := []int{0x11, 0x22, 0x33, 0x44} 41 dumpSliceInt(&sl1) 42 43 sl2 := sl1[1:] 44 dumpSliceInt(&sl2) 45}

実行結果

lang

1---- slice object ---- 2c208039f78 : 409f0308 c2000000 04000000 00000000 3c208039f88 : 04000000 00000000 4---- sliced array ---- 5c208039f40 : 11000000 00000000 22000000 00000000 6c208039f50 : 33000000 00000000 44000000 00000000 7 8---- slice object ---- 9c208039f60 : 489f0308 c2000000 03000000 00000000 10c208039f70 : 03000000 00000000 11---- sliced array ---- 12c208039f48 : 22000000 00000000 33000000 00000000 13c208039f58 : 44000000 00000000

補足:処理作成の動機
大規模無停止システムでは、メモリ管理は動的な処理系に任せず起動時に
メモリのバケットとして確保、必要時の確保・解放を自前の関数で行う設計が
執られる事があります(ソフト全体では、数百万ユーザのセッション情報の
構造体がポインタを介して複雑に絡む)。システム無停止が絶対条件であり、
メモリリークが起きた場合でもプログラム自身でそれを検知し対処できる
ようにするためです。また、必要時には外部からメモリ内容を手動で
追跡・変更して復旧させ得る必要があるためです。
メモリをそのオブジェクトによらずリニアに出力するという要件が発生します。

お答えいただけると助かります。よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

キャパシティの指定を伴う再スライスを上手に使うという手があります。
参考: http://golang.org/ref/spec#Slice_expressions
これを利用するとGo配列の一部だけを切り分けて他のコードに見せたり、Goポインタを頼りに回収する関数群(もしくはメソッド群)を書くことができるはずです。
最初は最低限のサイズのGo配列を作成しておき、足りなくなったら別なGo配列を追加してそこから空き要素を見つけるなどの処理が考えられます。アプリケーションコードに渡されたスライスからも自作メモリ管理部からも参照されなくなったGo配列は、自動的にガベージコレクタによって回収される可能性はあります。
ダンプの際にはその配列の内容をunsafeを使わずに書き出しておくのです。

勘違いがあればごめんなさい。

投稿2015/06/19 07:24

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/06/19 07:31

細かいメモリ管理をGoの範囲内で行うコードは標準ライブラリのソースコードにも見つかります。読んでみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問