Submit Search
Upload
マーク&スイープ勉強会
•
9 likes
•
5,694 views
7shi
Follow
マーク&スイープ勉強会の発表資料です。
Read less
Read more
Technology
Report
Share
Report
Share
1 of 39
Download now
Download to read offline
Recommended
メタプログラミングって何だろう
メタプログラミングって何だろう
Kota Mizushima
LLVM最適化のこつ
LLVM最適化のこつ
MITSUNARI Shigeo
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
MITSUNARI Shigeo
「日本語LaTeX」が多すぎる件について
「日本語LaTeX」が多すぎる件について
Takayuki Yato
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
Yuki Miyatake
DockerコンテナでGitを使う
DockerコンテナでGitを使う
Kazuhiro Suga
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
CODE BLUE
Recommended
メタプログラミングって何だろう
メタプログラミングって何だろう
Kota Mizushima
LLVM最適化のこつ
LLVM最適化のこつ
MITSUNARI Shigeo
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
MITSUNARI Shigeo
「日本語LaTeX」が多すぎる件について
「日本語LaTeX」が多すぎる件について
Takayuki Yato
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
Yuki Miyatake
DockerコンテナでGitを使う
DockerコンテナでGitを使う
Kazuhiro Suga
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
CODE BLUE
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
Nobuhisa Koizumi
自動定理証明の紹介
自動定理証明の紹介
Masahiro Sakai
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
sonickun
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
型安全性入門
型安全性入門
Akinori Abe
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Preferred Networks
Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?
Takayuki Shimizukawa
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
Clojureの世界と実際のWeb開発
Clojureの世界と実際のWeb開発
Tsutomu Yano
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
Fixstars Corporation
SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更
T. Suwa
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
masayoshi takahashi
Pythonによる黒魔術入門
Pythonによる黒魔術入門
大樹 小倉
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
kiki utagawa
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解
MITSUNARI Shigeo
katagaitai CTF勉強会 #5 Crypto
katagaitai CTF勉強会 #5 Crypto
trmr
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!
Ra Zon
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
SECCON Beginners
Glibc malloc internal
Glibc malloc internal
Motohiro KOSAKI
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
Yoshitaka Kawashima
Cコンパイラの改造(未)
Cコンパイラの改造(未)
7shi
ELFの動的リンク
ELFの動的リンク
7shi
More Related Content
What's hot
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
Nobuhisa Koizumi
自動定理証明の紹介
自動定理証明の紹介
Masahiro Sakai
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
sonickun
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
型安全性入門
型安全性入門
Akinori Abe
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Preferred Networks
Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?
Takayuki Shimizukawa
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
Clojureの世界と実際のWeb開発
Clojureの世界と実際のWeb開発
Tsutomu Yano
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
Fixstars Corporation
SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更
T. Suwa
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
masayoshi takahashi
Pythonによる黒魔術入門
Pythonによる黒魔術入門
大樹 小倉
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
kiki utagawa
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解
MITSUNARI Shigeo
katagaitai CTF勉強会 #5 Crypto
katagaitai CTF勉強会 #5 Crypto
trmr
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!
Ra Zon
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
SECCON Beginners
Glibc malloc internal
Glibc malloc internal
Motohiro KOSAKI
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
Yoshitaka Kawashima
What's hot
(20)
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
自動定理証明の紹介
自動定理証明の紹介
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
型安全性入門
型安全性入門
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Clojureの世界と実際のWeb開発
Clojureの世界と実際のWeb開発
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
Pythonによる黒魔術入門
Pythonによる黒魔術入門
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解
katagaitai CTF勉強会 #5 Crypto
katagaitai CTF勉強会 #5 Crypto
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
Glibc malloc internal
Glibc malloc internal
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
Viewers also liked
Cコンパイラの改造(未)
Cコンパイラの改造(未)
7shi
ELFの動的リンク
ELFの動的リンク
7shi
GCについて
GCについて
cactusman
GCが止まらない
GCが止まらない
Narihiro Nakamura
お絵描きソフト「PaintField」の開発
お絵描きソフト「PaintField」の開発
seanchas_t
F#とトランスレータ
F#とトランスレータ
7shi
無料環境でWindows Mobileアプリ開発
無料環境でWindows Mobileアプリ開発
7shi
V6でJIT・部分適用・継続
V6でJIT・部分適用・継続
7shi
Rcppのすすめ
Rcppのすすめ
Masaki Tsuda
Exploring the Performance Impact of Virtualization on an HPC Cloud
Exploring the Performance Impact of Virtualization on an HPC Cloud
Ryousei Takano
[学内勉強会]C++11とdirectxライブラリ
[学内勉強会]C++11とdirectxライブラリ
Shota Homma
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
Ryousei Takano
ELF
ELF
Koganti Ravikumar
OSvの概要と実装
OSvの概要と実装
Takuya ASADA
C++11とゲーム製作
C++11とゲーム製作
uchan_nos
Qt小技(修正版)
Qt小技(修正版)
hermit4 Ishida
エクストリームC++11/14プログラミング
エクストリームC++11/14プログラミング
egtra
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
Ryo Suzuki
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
Viewers also liked
(19)
Cコンパイラの改造(未)
Cコンパイラの改造(未)
ELFの動的リンク
ELFの動的リンク
GCについて
GCについて
GCが止まらない
GCが止まらない
お絵描きソフト「PaintField」の開発
お絵描きソフト「PaintField」の開発
F#とトランスレータ
F#とトランスレータ
無料環境でWindows Mobileアプリ開発
無料環境でWindows Mobileアプリ開発
V6でJIT・部分適用・継続
V6でJIT・部分適用・継続
Rcppのすすめ
Rcppのすすめ
Exploring the Performance Impact of Virtualization on an HPC Cloud
Exploring the Performance Impact of Virtualization on an HPC Cloud
[学内勉強会]C++11とdirectxライブラリ
[学内勉強会]C++11とdirectxライブラリ
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
ELF
ELF
OSvの概要と実装
OSvの概要と実装
C++11とゲーム製作
C++11とゲーム製作
Qt小技(修正版)
Qt小技(修正版)
エクストリームC++11/14プログラミング
エクストリームC++11/14プログラミング
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Similar to マーク&スイープ勉強会
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya
Dive into RTS - another side
Dive into RTS - another side
Kiwamu Okabe
Precise garbage collection for c
Precise garbage collection for c
miura1729
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
bitter_fox
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
natrium11321
PL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database Analytics
Kohei KaiGai
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
NVIDIA Japan
Objc lambda
Objc lambda
matuura_core
普通のコードがCodeGolfコードになるまで in Ruby
普通のコードがCodeGolfコードになるまで in Ruby
Akito Sano
PBL1-v1-007j.pptx
PBL1-v1-007j.pptx
NAIST
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
Yoshiyuki Asaba
出張 CTF for ビギナーズ 2015 幕張 in セキュリティ・キャンプ 成果報告
出張 CTF for ビギナーズ 2015 幕張 in セキュリティ・キャンプ 成果報告
Ikumi Shimizu
N3495 inplace realloc
N3495 inplace realloc
Takatoshi Kondo
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミング
Kiwamu Okabe
Brief introduction of Boost.ICL
Brief introduction of Boost.ICL
yak1ex
PBL1-v1-008j.pptx
PBL1-v1-008j.pptx
NAIST
Introduction to OpenCL (Japanese, OpenCLの基礎)
Introduction to OpenCL (Japanese, OpenCLの基礎)
Takahiro Harada
Prosym2012
Prosym2012
MITSUNARI Shigeo
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
digitalghost
emc++ chapter32
emc++ chapter32
Tatsuki SHIMIZU
Similar to マーク&スイープ勉強会
(20)
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
Dive into RTS - another side
Dive into RTS - another side
Precise garbage collection for c
Precise garbage collection for c
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
PL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database Analytics
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
Objc lambda
Objc lambda
普通のコードがCodeGolfコードになるまで in Ruby
普通のコードがCodeGolfコードになるまで in Ruby
PBL1-v1-007j.pptx
PBL1-v1-007j.pptx
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
出張 CTF for ビギナーズ 2015 幕張 in セキュリティ・キャンプ 成果報告
出張 CTF for ビギナーズ 2015 幕張 in セキュリティ・キャンプ 成果報告
N3495 inplace realloc
N3495 inplace realloc
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミング
Brief introduction of Boost.ICL
Brief introduction of Boost.ICL
PBL1-v1-008j.pptx
PBL1-v1-008j.pptx
Introduction to OpenCL (Japanese, OpenCLの基礎)
Introduction to OpenCL (Japanese, OpenCLの基礎)
Prosym2012
Prosym2012
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
emc++ chapter32
emc++ chapter32
More from 7shi
F#談話室(3) LT
F#談話室(3) LT
7shi
ZIP勉強会
ZIP勉強会
7shi
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
7shi
Deflate
Deflate
7shi
CRC-32
CRC-32
7shi
LLPML
LLPML
7shi
More from 7shi
(6)
F#談話室(3) LT
F#談話室(3) LT
ZIP勉強会
ZIP勉強会
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
Deflate
Deflate
CRC-32
CRC-32
LLPML
LLPML
Recently uploaded
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
UEHARA, Tetsutaro
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
Yuki Kikuchi
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
FumieNakayama
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
FumieNakayama
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
Hiroshi Tomioka
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
akihisamiyanaga1
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
博三 太田
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
sugiuralab
Recently uploaded
(8)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
マーク&スイープ勉強会
1.
マーク&スイープ勉強会 七誌
2.
マーク&スイープ • GCのアルゴリズムの一種 • GC中はプログラムが停止する –
これはstop the worldと呼ばれる • 停止時間を短くするために色々な工夫がある – 世代別GC、Concurrent GCなど • これらはマーク&スイープの発展系 • 今回は基礎となる単純なマーク&スイープに 的を絞る
3.
今回の流れ • 単純なマーク&スイープGCを実装する • 対象はシングルスレッドに限定 –
マルチスレッドは単純なマーク&スイープでは対 応できないため、前のスライドで取り上げたような 発展系のアルゴリズムが必要 • 大まかに説明した後、実装のための自由時 間とします – 自由時間を長めに取りたいので、説明はざっくり – 自由時間に質問を受け付けます。お気軽に!
4.
第1部 メモリを覗いてみよう
5.
ローカル変数 (1) • まず次のようなケースで、使用しなくなったポ インタをどう検出するか考える #include
<stdlib.h> int main() { void *a = malloc(10); void *b = malloc(10); a = NULL; } 2. 宙に浮く 1. ポインタを上書き
6.
ローカル変数 (2) • メモリ管理やポインタについて調べる前に、 ローカル変数がメモリにどう格納されている のかを確認する #include
<stdio.h> int main() { int a = 0x12345678, b = 0xcafebabe; printf("&a: %p¥n", &a); printf("&b: %p¥n", &b); } &a: 0028FF1C &b: 0028FF18 実行結果
7.
ローカル変数 (3) • デバッガで見てみる 入力
8.
スタックフレーム (1) • ローカル変数周りのメモリは、大まかに以下のよう な構造になっている •
この構造をスタックフレームと呼ぶ アドレス 小 大 (ワークエリア) ローカル変数 (ワークエリア) 引数
9.
スタックフレーム (2) • ローカル変数より引数のアドレスが大きいこ とを確認してみる #include
<stdio.h> int main(int argc, char *argv[]) { int a; printf("&a : %p¥n", &a); printf("&argc: %p¥n", &argc); printf("&argv: %p¥n", &argv); } &a : 0028FF1C &argc: 0028FF30 &argv: 0028FF34 実行結果
10.
スタックフレーム (3) • 関数を呼び出すと、スタックフレームはどんどん上 (アドレスの小さい方)に積み重なる アドレス 小 大 void
b() { } void a() { b(); } b() の スタックフレーム a() の スタックフレーム a() から b() を呼ぶ
11.
スタックフレーム (4) • 関数を呼び出すとスタックフレームが上に積 み重なることを確認してみる #include
<stdio.h> int b(int a) { printf("&a : %p¥n", &a); } int main(int argc, char *argv[]) { printf("&argc: %p¥n", &argc); b(0); } &argc: 0028FF30 &a : 0028FF10 実行結果
12.
変数探し • スタックフレームを走査して変数を検出 #include <stdio.h> void
search(int *start, int value) { for (int *p = start; p > &value; p--) { if (*p == value) { printf("found: %p¥n", p); return; } } } int main(int argc, char *argv[]) { int a = 0xcafebabe; printf("&a: %p¥n", &a); search(&argc, a); } &a: 0028FF1C found: 0028FF1C 実行結果
13.
malloc (1) • 冒頭の問題に戻る #include
<stdlib.h> int main() { void *a = malloc(10); void *b = malloc(10); a = NULL; } • malloc() の戻り値を記録しておいて、スタック フレームに含まれるか確認すれば良い
14.
malloc (2) • malloc()
の戻り値を記録する例 #include <stdlib.h> #include <map> static std::map<void *, bool> mallocs; void *gc_malloc(size_t size) { void *ret = malloc(size); mallocs[ret] = true; return ret; }
15.
問題 1 • 以下のコードで使われている
gc_init(), gc_malloc(), gc_collect() を実装してください。 • ※ 最初に掲示した問題を改変しました。 #include <stdlib.h> int main(int argc, char *argv[]) { gc_init(&argc); void *a = gc_malloc(10); void *b = gc_malloc(10); a = NULL; gc_collect(); }
16.
問題 1 の回答例 static
void **stack_start; void gc_init(int *pargc) { stack_start = reinterpret_cast<void **>(pargc); } void gc_collect() { void *end; for (auto it = mallocs.begin(); it != mallocs.end(); ++it) it->second = false; for (auto p = stack_start; p > &end; p--) if (mallocs.find(*p) != mallocs.end()) mallocs[*p] = true; for (auto it = mallocs.begin(); it != mallocs.end();) if (it->second) ++it; else { free(it->first); mallocs.erase(it++); } }
17.
マーク&スイープ 問題 1 の回答例について説明 1.
mallocsの値をすべてfalseにする 2. スタックフレームを走査して、見付けたもの をtrueにする 3. falseのままになっている領域を解放する 2のフェーズをマーク、3をスイープと呼ぶ
18.
保守的なGC • 偶然 mallocsに含まれるのと同じ値がメモリ に含まれている可能性がある。 •
その場合、解放されないまま残る。 • GCが誤って解放し過ぎるとアクセスしたとき に落ちるが、解放されずに残っても多少リー クする程度で実害はない。 • そのように割り切ったGCを『保守的なGC』と 呼ぶ。
19.
第2部 ポインタを追ってみよう
20.
問題 2 • 生きている領域が解放されないようにGCを 修正してください。 #include
<stdlib.h> struct Test { void *ptr; }; int main(int argc, char *argv[]) { gc_init(&argc); Test *t = reinterpret_cast<Test *>( gc_malloc(sizeof(Test))); t->ptr = gc_malloc(10); gc_collect(); } 生きているのに 回収されてしまう!
21.
問題 2 の回答例(抜粋) struct
HeapInfo { size_t size, sizep; bool marked; }; static std::map<void *, HeapInfo> mallocs; void *gc_malloc(size_t size) { void *ret = malloc(size); HeapInfo hi = { size, size / sizeof(void *), true }; mallocs[ret] = hi; return ret; } static void gc_scan(void **start, void **end) { for (auto p = start; p < end; p++) { auto it = mallocs.find(*p); if (it != mallocs.end() && !it->second.marked) { it->second.marked = true; auto pp = reinterpret_cast<void **>(*p); gc_scan(pp, pp + it->second.sizep); } } }
22.
問題 3 • 無駄なスキャンを抑制してください。 struct
Test { void *ptr; int *buf; }; int main(int argc, char *argv[]) { gc_init(&argc); Test *t = reinterpret_cast<Test *>( gc_malloc(sizeof(Test))); t->ptr = gc_malloc(10); t->buf = reinterpret_cast<int *>( gc_malloc(1024 * 1024)); gc_collect(); } ポインタが含まれていない 内部の走査は無駄!
23.
問題 3 の回答例(抜粋) •
内部を走査するか指定できるようにする struct HeapInfo { size_t size, sizep; bool marked, scan; }; void *gc_malloc(size_t size, bool scan = true) { 略 } static void gc_scan(void **start, void **end) { 略 it->second.marked = true; if (it->second.scan) { 略 } 略 } int main(int argc, char *argv[]) { 略 t->buf = reinterpret_cast<int *>( gc_malloc(1024 * 1024, false)); gc_collect(); }
24.
第3部 C++で使いやすく
25.
new (1) • 以前出てきた例を改めて見返すと・・・ #include
<stdlib.h> struct Test { void *ptr; }; int main(int argc, char *argv[]) { gc_init(&argc); Test *t = reinterpret_cast<Test *>( gc_malloc(sizeof(Test))); t->ptr = gc_malloc(10); gc_collect(); } いくら何でも冗長過ぎる! newで簡単に書けないか?
26.
new (2) • operator
newを置き換えると無条件にGC対 象となってしまうため、意図的にGCを外した いときに不便 • newした後、GCに登録する関数を用意 • 常にGC対象にしたいクラスはコンストラクタ で自分を登録すれば良い Test *t = gc_register(new Test); struct Test { Test() { gc_register(this); } };
27.
new (3) • deleteで解放するため、解放処理をコール バックとして登録できるようにする •
free() と同じ型の関数ポインタで登録するた め、delete のラッパーを用意 template <class T> void gc_delete(void *p) { delete reinterpret_cast<T *>(p); } template <class T> void gc_delete_array(void *p) { delete [] reinterpret_cast<T *>(p); }
28.
実装例(抜粋) struct HeapInfo { size_t
size, sizep; bool marked, scan; void (*free)(void *); }; void gc_register(void *p, size_t size, bool scan, void (*free)(void *)) { HeapInfo hi = { size, size / sizeof(void *), true, scan, free }; mallocs[p] = hi; } void *gc_malloc(size_t size, bool scan = true) { void *ret = malloc(size); gc_register(ret, size, scan, free); return ret; } template <class T> T *gc_register(T *t) { gc_register(t, sizeof(T), true, gc_delete<T>); return t; }
29.
GCポインタ (1) • グローバル変数や非GC対象インスタンスのメンバ は走査対象とならない int
*p = gc_new<int>(); struct Test { int *ptr; }; int main(int argc, char *argv[]) { gc_init(&argc); Test *t = new Test; t->ptr = gc_new<int>(); gc_collect(); } 生きているのに 回収されてしまう!
30.
GCポインタ (2) • スマートポインタと同じような発想でGCポイン タを作ってマーク対象とする gc_ptr<int>
p = gc_new<int>(); struct Test { gc_ptr<int> ptr; }; int main(int argc, char *argv[]) { gc_init(&argc); Test *t = new Test; t->ptr = gc_new<int>(); gc_collect(); }
31.
実装例(抜粋) static std::list<void **>
gc_ptrs; template <class T> class gc_ptr { T *ptr; std::list<void **>::iterator it; void init(T *p) { ptr = p; gc_ptrs.push_back(reinterpret_cast<void **>(&ptr)); it = --gc_ptrs.end(); } public: gc_ptr() { init(NULL); } gc_ptr(const gc_ptr<T> &p) { init(p.ptr); } gc_ptr(T *p) { init(p); } ~gc_ptr() { gc_ptrs.erase(it); } gc_ptr<T> &operator =(T *p) { ptr = p; return *this; } inline operator T *() const { return ptr; } };
32.
クロージャ (1) • C++のラムダ式はキャプチャによって環境を 閉じ込めているわけではないため、厳密には クロージャではないと言われる •
以下の例ではローカル変数をキャプチャして いるが、単なる参照のため、スコープアウト後 に使用してはいけない std::function<int()> test() { int a = 0; return [&] { return ++a; }; }
33.
クロージャ (2) • GCがあれば、キャプチャ対象を気軽にヒープ に確保することができる std::function<int()>
test() { gc_ptr<int> a = gc_new<int>(); *a = 0; return [=] { return ++(*a); }; } int main() { auto f = test(); printf("%d¥n", f()); gc_collect(); printf("%d¥n", f()); f = [] { return 0; }; gc_collect(); printf("%d¥n", f()); } ここでキャプチャされた aが指す先が解放される
34.
クロージャ (3) • ヒープを使う方式は、ローカル変数のキャプ チャに参照を使う
F# と同じ構造 • ヒープへのポインタを値束縛することで、環境 を閉じ込めたように見せかけている std::function<int()> test() { gc_ptr<int> a = gc_new<int>(); *a = 0; return [=] { return ++(*a); }; } C++ with GC let test () = let a = ref 0 fun () -> a := !a + 1; !a F#
35.
第4部 自動調節
36.
閾値 (1) • 今までは手動で
gc_collect を呼んでいた • GCに登録するときに使用メモリ量をカウント して、閾値を超えたら呼ぶことで自動化 static size_t mem_used; static size_t threshold = 1024 * 1024; void gc_register(void *p, size_t size, bool scan, void (*free)(void *)) { HeapInfo hi = { size, size / sizeof(void *), true, scan, free }; mallocs[p] = hi; mem_used += size; if (mem_used > threshold) gc_collect(); }
37.
閾値 (2) • スイープの際に使用メモリ量を減らす •
最終的に確定した使用量で閾値を調整 void gc_collect(void *dummy) { 略 for (auto it = mallocs.begin(); it != mallocs.end();) { if (it->second.marked) ++it; else { printf("sweep: %p¥n", it->first); (*it->second.free)(it->first); mem_used -= it->second.size; mallocs.erase(it++); } } while (mem_used > (threshold >> 1)) threshold <<= 1; }
38.
閾値 (3) • 自動的に
gc_collect() が呼ばれるようになる int main(int argc, char *argv[]) { gc_init(&argc); for (int i = 0; i < 10; i++) gc_malloc(300 * 1024, false); } • 処理内容によってGCの特性は異なる – 巨大なサイズが少数確保される場合 – 小さいサイズが大量に確保される場合 • サイズや個数も考慮すると効率が上がる
39.
ご清聴ありがとうございました
Download now