NULL
OSはプロセスがこの場所にメモリを割り当てることを許可していないため、(0x00000000)は何もポインタではないことを私は知っています。しかし、0x00000001(マジックナンバーまたはコードポインター)を使用する場合、OSがここでメモリを割り当てることを許可しないと想定しても安全ですか?もしそうなら、どこまでそれを仮定するのが安全ですか?
6 に答える
標準(最初)
0
標準は、ポインタが行く限り、それが番兵値であることを保証するだけです。基礎となるメモリ表現は保証されていません。実装が定義されています。
ポインター状態の読み取りまたは新しい状態の書き込み(間接参照またはポインター演算を含む)以外の目的でその番兵値に設定されたポインターを使用することは、未定義の動作です。
仮想メモリ
仮想メモリの時代(つまり、各プロセスは他のプロセスから独立して独自のメモリスペースを取得します)、nullポインタは、ほとんどの場合、プロセスメモリスペースで0として表されます。メインフレームではそうではないかもしれないと思いますが、実際には他のアーキテクチャについては知りません。
Unix
Unixの世界では、0x8000未満のすべてのアドレス空間をnull値用に予約するのが一般的です。メモリは割り当てられていません。実際には、保護されているだけです(つまり、特別なモードになっています)。そのため、メモリの読み取りまたは書き込みを試みた場合、OSはセグメンテーション違反をトリガーします。
このような範囲を使用するという考え方は、nullポインターが必ずしもそのまま使用されるとは限らないということです。たとえば、std::pair<int, int>* p = 0;
nullを使用してを呼び出すと、コンパイラは(つまり一般的に)p->second
ポイントするために必要な算術演算を実行し、でメモリに直接アクセスしようとします。問題は明らかにアレイによって悪化します。second
+4
0x4
実際には、この0x8000
制限は、ほとんどの問題を検出する(そしてメモリの破損などを回避する)のに十分実用的である必要があります。この場合、これは、未定義の動作を回避し、「適切な」クラッシュが発生することを意味します。ただし、大きなアレイを使用している場合は、それをオーバーシュートする可能性があるため、特効薬ではありません。
実装またはコンパイラ/ランタイムスタックの特定の制限は、ドキュメントまたは連続した試行によって決定できます。それを微調整する方法さえあるかもしれません。
ポインタの実際の値については何も想定しないでください。特に、リテラルがゼロのように見えても、ヌルポインタをゼロアドレスで表す必要はありません。0
唯一の有効な範囲は、OSによって割り当てられた範囲であると想定されています。それ以外の場合は、OSによって拒否されます。
その規則の例外は共有メモリです。
C ++標準は、ゼロ(null)以外のポインタアドレスを「予約」しません。したがって、1またはその他の値を「魔法の」ポインタ値として使用することは安全ではありません。もちろん、実際には、c++の一部の実装はおそらくすべてが特定の値を使用するわけではありません。ただし、言語定義からは何の保証もありません。
最近のOSは、NULLポインター用に少なくとも1ページを予約する可能性があります。したがって、0x1(または32ビットアライメントが必要な場合は0x4)が機能する可能性があります。
ただし、これはC /C++言語では保証されないことに注意してください。このような動作については、OSとコンパイラに依存する必要があります。
さらに、NULLポインタの実際の値についての保証はありません。すべてゼロである場合とそうでない場合があります。そうでない場合、あなたのトリックはまったく機能しません。
I will try to give a broad view about this:
- you probably will never ever access the real memory addresses because of the multiple sandboxing mechanism that every modern OS has and puts in place.
- What is a NULL pointer from the software viewpoint ? a NULL pointer is a pointer variable that stores a value that the programmer pick as a meaningfull value and this value is used as a label with the following meaning "this pointer goes nowhere". a NULL pointer does not point to 0x000000 by definition, the definition of a NULL pointer it's not about where that pointer will point to but the value of this macro called NULL and this value will be the value of this NULL pointer.
- in C you can assume that
NULL == 0
, only in C NULL is a macro that defines NULL as an int that is equal to 0, in C++ you do not have this liberty - there are types, labels and values ( in better terms, representations of values not real values ) for every variables, at least for primitives values, the same is for the pointers, if you are speaking about void pointers you are speaking about pointers that contains a memory address ( just like any pointer ) and the only special thing about this pointers is that they need a cast in C++ to be decoded, safely and effectively; it's a big mistake if you think about
void*
as pointers that points to nowhere or to0
or toNULL
or to0x0000000
by the way, i still don't get your problem ...