page0006
の編集
http://osecpu.osask.jp/wiki/?page0006
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
BracketName
FormattingRules
FrontPage
Fulyn
Fulyn-v2
Fulyn_Samples
Help
InterWiki
InterWikiName
InterWikiSandBox
K
KOR_PIT8254
KWVM.NET
Liva
MANA
MenuBar
OSECPU_FPGA
PG_MANA
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
WikiEngines
WikiName
WikiWikiWeb
YukiWiki
hikalium
hikarupsp
hikarupsp_ELCHNOS
hikarupsp_ELCHNOS_IDE
hikarupsp_FrontEndCode
hikarupsp_WebCPU-VM
hikarupsp_WebCPU-VM_internal
hikarupsp_study_hh4
impressions
impressions0000
jpag0000
jpag0001
jpag0002
jpag0003
jpag0004
jpag0005
lambdalice
mandel59
members
memo0000
memo0001
memo0002
memo0003
memo0004
memo0005
memo0006
memo0007
memo0008
memo0009
memo0010
osask
osecpu4android
page0000
page0001
page0002
page0003
page0004
page0005
page0006
page0007
page0008
page0009
page0010
page0011
page0012
page0013
page0014
page0015
page0016
page0017
page0018
page0019
page0020
page0021
page0022
page0023
page0024
page0025
page0026
page0027
page0028
page0029
page0030
page0031
page0032
page0033
page0034
page0035
page0036
page0037
page0038
page0039
page0040
page0041
page0042
page0043
page0044
page0045
page0046
page0047
page0048
page0049
page0050
page0051
page0052
page0053
page0054
page0055
page0056
page0057
page0058
page0059
page0060
page0061
page0062
page0063
page0064
page0065
page0066
page0067
page0068
page0069
page0070
page0071
page0072
page0073
page0074
page0075
page0076
page0077
page0078
page0079
page0080
page0081
page0082
page0083
page0084
page0085
page0086
page0087
page0088
page0089
page0090
page0091
page0092
page0093
page0094
page0095
page0096
page0097
page0098
page0099
page0100
page0101
page0102
page0103
page0104
page0105
page0106
page0107
page0108
page0109
pagenames
populars
seccamp2013
seccamp2014
seccamp2017
ttwilb
ttwilb-asmi
yao
* OSECPUでのポインタの扱い -(by [[K]], 2013.03.12) ** テーマ1 int *a = malloc(1234); free(a); a[123] = 123; -このプログラムは明らかにまずい、free()したあとのメモリに触っている。だからこれをちゃんと検出できる仕組みを作りたい。 ---- -ポインタレジスタを128itにする。そのうちの32bitは普通のポインタで、残りの96bitはいろいろな情報を詰め込む。この96bit部分についてはアプリは読み書きできない。 --void *p; // ポインタ本体 --PTRHND *phnd; // ポインタハンドル --int sign; // シグネチャ --int dummy; // リザーブ -ポインタハンドルを参照すれば、このポインタpの参照先のメモリがいつどこでmallocされたメモリに属しているかが分かる。この中にはシグネチャ(乱数でmalloc時に生成)も書かれている。 -ポインタを初期化する時に、ポインタハンドルからシグネチャをコピーしてくる。 -そしてポインタを使ってアクセスする時は、ポインタハンドルのシグネチャとポインタの中のシグネチャが一致しているかどうか比較する。不一致ならバグ検出エラーである。 -freeした場合、ポインタハンドルの先のシグネチャは乱数で上書きされる。だからfreeしたあとでポインタを再度使ってしまうミスはすべて検出できる。 --乱数がたまたま一致してしまった!という場合は突破できてしまうけど、乱数以外のうまい方法を思いつかず・・・。 ** テーマ2 -[テーマ1]で「バグ検出エラー」が出るのは非常にうれしいけど、じゃあどのfreeのせいで使えなくなったのかを教えてくれたらもっとうれしい。 -それはfree時にポインタハンドルに情報を書き残しておけばよい。 -でもポインタハンドルを別のオブジェクトの管理のために再利用してしまう可能性がある!・・・だってそうしないとmalloc/freeを繰り返すプログラムがあったら、いつかメモリがなくなってしまう! -ということで、malloc()時にポインタハンドルを再利用しないでねっていうデバッグ用オプションをつけられるようにする。デバッグで追跡する時は、怪しいところにこのフラグをつけておきましょう。 --なおプログラムが高速危険モードで実行されている時は、このフラグは無視されます。 --そもそも高速危険モードの場合は、いくつかのバグ検出機能もOFFになっています。全部OFFになっている可能性もあります。 ** テーマ3 -[テーマ1]や[テーマ2]で、不適切なfree()は多分容易に発見できるようになったと思います、思いたい!・・・次はfreeが足りない場合を考えます。 --要するにメモリリークですね。 -これはプログラムの実行中の好きなタイミングで、ポインタハンドルの一覧が見られたらいいのかなと思いました。 --ポインタハンドルにはいろんな情報がつまっています。malloc()時にいろんな情報をもらいます。 -これで「あれ?このオブジェクトがどうしてまだ居座っているんだ?」ってなって気づくことができるのではないかと・・・。 --ループする度にリークしているのが分かったりしたらいいですよね。 ** テーマ5 -OSECPUのデータポインタにできること、できないこと。まとめ。 --仕様を詰めたのでやっと断言できるようになりました。 -(1) unionは使えません(そういう構文がない)。 -(2) 互換性のあるポインタへのキャストはできます。 -(3) int a[3]; で宣言されているのなら、a[3]へはアクセスできません。a[-1]もできません。 -(4) 2つのポインタを大小比較することができますが、これは両ポインタが同じ配列に属している場合に限られます。 -(5) 大きな配列から部分配列を作ることができます(これは配列のコピーをするわけではありません・・・もちろんコピーして部分配列を作ることもできます)。 -(6) 型を間違えたらエラーです。 -(7) OSECPUのCPUはPxxについて、型情報やアクセス可能域に関する情報を持っていますが、これはエラー判定のためだけに使われることになっていて、これらの情報を取得する命令は一切ありません。 -(8) ADDPTR命令でポインタのシークができますが、この時アクセス域を超えてしまったらその時点でエラーです。結果はC言語と同様にクラスのサイズでスケールします。 --つまり実際にメモリアクセスを発生させなくてもエラーが出ます。 --この仕様はやめました(by K, 2013.07.08)。PADDだけではエラーは出ません。 -(9) SUBPTR命令で二つのポインタの引き算ができますが、これは比較可能なポインタ同士でなければエラーです。結果はC言語と同様にクラスのサイズでスケールします。 -(10) メモリ上の値の符号の有無やエンディアンについては、JITCが自動で判定します。この決定に逆らうことはできません。ですから signed char のメモリに対して、ゼロ拡張のリードはできないのです。 -(11) たとえば signed char のメモリに対して128を書き込もうとしたらエラーです。 --このエラーを検出できない可能性もあります・・・すみません! -(12) [テーマ1]のようにfree()したメモリ域を指しているポインタはすべて無効になっています。 -(13) realloc()ではメモリ域を縮小する場合であっても、ポインタが更新されます。 --これは同じ領域を指している他のポインタを確実に無効化するためで、新しいサイズを確保してコピーした後、古いオブジェクトはfreeされるのです。 -(14) malloc()でint4個分の領域を取ったのなら、やはりそこより先にはシークもアクセスもできません。 -(15) int a[4][4]; のような配列があったとして、これを int *b = a[0]; にすることはできます。そしてb[4]は間違いなくa[1][0]を指しているわけですが、b[4]はエラーになってアクセスできません。 --これをどうしてもやりたいときはint b[16];で領域を確保して、a[][]の内容をコピーしてください。それ以外の方法は用意しません。 -(16) データポインタにJMPすることはできません。しかしOSを使えばメモリ上にOSECPUのバイトコードを並べた状態で、それにJITコンパイラをかけることができ、その際は結果として分岐可能なポインタが返されます。 --これを使えば言語処理系みたいなものも作れますね! --C言語ではこれが標準の範囲ではできません。プログラム内でC言語のソースを生成しても、実行できる保証はないのです。gccをsystem()関数で起動しますか?そして出力された実行ファイルをsystem()で起動しますか?いずれにせよ、それは環境依存の方法です。 -(17) ある命令に対して、エラーを起こすかどうかをチェックする命令はありません。またエラーが起きた時にそれをエラーハンドラというか例外ハンドラで受ける方法もありません。 --この手のポインタのエラーは、普通のプログラムのやり方で容易に防げるものです。ですからOSECPUのエラー検出能力に頼ってはいけません。 ** テーマ6 -システムコールから戻る時にレジスタを放置して大事なポインタが流出してしまったらどうしよう? -システムコールから帰るときはやばいポインタが残っていないかチェックする?というかやばいポインタってどうやってOSが入手するんだ?結局はこんなこと気にする必要がない??? ** こめんと欄 -このページにこめんと欄はありません。このページの内容にコメントしたいときは[[impressions]]にお願いします。
タイムスタンプを変更しない
* OSECPUでのポインタの扱い -(by [[K]], 2013.03.12) ** テーマ1 int *a = malloc(1234); free(a); a[123] = 123; -このプログラムは明らかにまずい、free()したあとのメモリに触っている。だからこれをちゃんと検出できる仕組みを作りたい。 ---- -ポインタレジスタを128itにする。そのうちの32bitは普通のポインタで、残りの96bitはいろいろな情報を詰め込む。この96bit部分についてはアプリは読み書きできない。 --void *p; // ポインタ本体 --PTRHND *phnd; // ポインタハンドル --int sign; // シグネチャ --int dummy; // リザーブ -ポインタハンドルを参照すれば、このポインタpの参照先のメモリがいつどこでmallocされたメモリに属しているかが分かる。この中にはシグネチャ(乱数でmalloc時に生成)も書かれている。 -ポインタを初期化する時に、ポインタハンドルからシグネチャをコピーしてくる。 -そしてポインタを使ってアクセスする時は、ポインタハンドルのシグネチャとポインタの中のシグネチャが一致しているかどうか比較する。不一致ならバグ検出エラーである。 -freeした場合、ポインタハンドルの先のシグネチャは乱数で上書きされる。だからfreeしたあとでポインタを再度使ってしまうミスはすべて検出できる。 --乱数がたまたま一致してしまった!という場合は突破できてしまうけど、乱数以外のうまい方法を思いつかず・・・。 ** テーマ2 -[テーマ1]で「バグ検出エラー」が出るのは非常にうれしいけど、じゃあどのfreeのせいで使えなくなったのかを教えてくれたらもっとうれしい。 -それはfree時にポインタハンドルに情報を書き残しておけばよい。 -でもポインタハンドルを別のオブジェクトの管理のために再利用してしまう可能性がある!・・・だってそうしないとmalloc/freeを繰り返すプログラムがあったら、いつかメモリがなくなってしまう! -ということで、malloc()時にポインタハンドルを再利用しないでねっていうデバッグ用オプションをつけられるようにする。デバッグで追跡する時は、怪しいところにこのフラグをつけておきましょう。 --なおプログラムが高速危険モードで実行されている時は、このフラグは無視されます。 --そもそも高速危険モードの場合は、いくつかのバグ検出機能もOFFになっています。全部OFFになっている可能性もあります。 ** テーマ3 -[テーマ1]や[テーマ2]で、不適切なfree()は多分容易に発見できるようになったと思います、思いたい!・・・次はfreeが足りない場合を考えます。 --要するにメモリリークですね。 -これはプログラムの実行中の好きなタイミングで、ポインタハンドルの一覧が見られたらいいのかなと思いました。 --ポインタハンドルにはいろんな情報がつまっています。malloc()時にいろんな情報をもらいます。 -これで「あれ?このオブジェクトがどうしてまだ居座っているんだ?」ってなって気づくことができるのではないかと・・・。 --ループする度にリークしているのが分かったりしたらいいですよね。 ** テーマ5 -OSECPUのデータポインタにできること、できないこと。まとめ。 --仕様を詰めたのでやっと断言できるようになりました。 -(1) unionは使えません(そういう構文がない)。 -(2) 互換性のあるポインタへのキャストはできます。 -(3) int a[3]; で宣言されているのなら、a[3]へはアクセスできません。a[-1]もできません。 -(4) 2つのポインタを大小比較することができますが、これは両ポインタが同じ配列に属している場合に限られます。 -(5) 大きな配列から部分配列を作ることができます(これは配列のコピーをするわけではありません・・・もちろんコピーして部分配列を作ることもできます)。 -(6) 型を間違えたらエラーです。 -(7) OSECPUのCPUはPxxについて、型情報やアクセス可能域に関する情報を持っていますが、これはエラー判定のためだけに使われることになっていて、これらの情報を取得する命令は一切ありません。 -(8) ADDPTR命令でポインタのシークができますが、この時アクセス域を超えてしまったらその時点でエラーです。結果はC言語と同様にクラスのサイズでスケールします。 --つまり実際にメモリアクセスを発生させなくてもエラーが出ます。 --この仕様はやめました(by K, 2013.07.08)。PADDだけではエラーは出ません。 -(9) SUBPTR命令で二つのポインタの引き算ができますが、これは比較可能なポインタ同士でなければエラーです。結果はC言語と同様にクラスのサイズでスケールします。 -(10) メモリ上の値の符号の有無やエンディアンについては、JITCが自動で判定します。この決定に逆らうことはできません。ですから signed char のメモリに対して、ゼロ拡張のリードはできないのです。 -(11) たとえば signed char のメモリに対して128を書き込もうとしたらエラーです。 --このエラーを検出できない可能性もあります・・・すみません! -(12) [テーマ1]のようにfree()したメモリ域を指しているポインタはすべて無効になっています。 -(13) realloc()ではメモリ域を縮小する場合であっても、ポインタが更新されます。 --これは同じ領域を指している他のポインタを確実に無効化するためで、新しいサイズを確保してコピーした後、古いオブジェクトはfreeされるのです。 -(14) malloc()でint4個分の領域を取ったのなら、やはりそこより先にはシークもアクセスもできません。 -(15) int a[4][4]; のような配列があったとして、これを int *b = a[0]; にすることはできます。そしてb[4]は間違いなくa[1][0]を指しているわけですが、b[4]はエラーになってアクセスできません。 --これをどうしてもやりたいときはint b[16];で領域を確保して、a[][]の内容をコピーしてください。それ以外の方法は用意しません。 -(16) データポインタにJMPすることはできません。しかしOSを使えばメモリ上にOSECPUのバイトコードを並べた状態で、それにJITコンパイラをかけることができ、その際は結果として分岐可能なポインタが返されます。 --これを使えば言語処理系みたいなものも作れますね! --C言語ではこれが標準の範囲ではできません。プログラム内でC言語のソースを生成しても、実行できる保証はないのです。gccをsystem()関数で起動しますか?そして出力された実行ファイルをsystem()で起動しますか?いずれにせよ、それは環境依存の方法です。 -(17) ある命令に対して、エラーを起こすかどうかをチェックする命令はありません。またエラーが起きた時にそれをエラーハンドラというか例外ハンドラで受ける方法もありません。 --この手のポインタのエラーは、普通のプログラムのやり方で容易に防げるものです。ですからOSECPUのエラー検出能力に頼ってはいけません。 ** テーマ6 -システムコールから戻る時にレジスタを放置して大事なポインタが流出してしまったらどうしよう? -システムコールから帰るときはやばいポインタが残っていないかチェックする?というかやばいポインタってどうやってOSが入手するんだ?結局はこんなこと気にする必要がない??? ** こめんと欄 -このページにこめんと欄はありません。このページの内容にコメントしたいときは[[impressions]]にお願いします。
テキスト整形のルールを表示する