5

私は何かのためにmallocを使用してコードを書いていて、問題に直面したので、実際に以下の混乱全体を要約するテストコードを書きました::

# include <stdio.h>
# include <stdlib.h>
# include <error.h>

int main()     
{
     int *p = NULL;
     void *t = NULL;
     unsigned short *d = NULL;

     t = malloc(2);
     if(t == NULL) perror("\n ERROR:");
     printf("\nSHORT:%d\n",sizeof(short));
     d =t;
     (*d) = 65536;
     p = t; 
     *p = 65536;
     printf("\nP:%p: D:%p:\n",p,d);
     printf("\nVAL_P:%d ## VAL_D:%d\n",(*p),(*d));
     return 0;
  }
   Output:: abhi@ubuntu:~/Desktop/ad/A1/CC$ ./test

            SHORT:2
            P:0x9512008: D:0x9512008:
            VAL_P:65536 ## VAL_D:0

malloc を使用して2 バイトのメモリを割り当てています。void* ポインタを返す mallocは void* ポインタ 't' に格納されます

その後、2 つのポインタがp-integer 型と d-short 型で宣言されます。次に、両方に t を割り当てました* (p =t and d=t) *これは、d と p の両方がヒープ上の同じメモリ位置を指していることを意味します。

65536(2^16) を (*d) に保存しようとすると、予想どおり大きな int 値が切り捨てられたという警告が表示されます。今、私は再び 65536(2^16) を (*p) に保存しましたが、警告は発生しませんでした。

* (*p) と ( d) の両方を印刷すると、異なる値が得られました (ただし、定義された独自のポインター型に対してはそれぞれ正しい)。

私の質問は次のとおりです。

  1. malloc を使用して 2 バイト (つまり 16 ビット) のヒープ mem を割り当てましたが、これらの 2 バイトに 65536 を保存するにはどうすればよいでしょうか (整数型のポインターである ( p) を使用して) ?? これの原因は、voidから int* ポインターへの自動型変換 (p =t) であると感じているので、t を p に割り当てると、 malloc によって割り当てられたもの以外のメモリ領域にアクセスすることになります。??.

  2. これはすべて、(*p) と (*d) を介して同じメモリ領域を参照解除する地獄がどのように起こっているかにかかわらず、2 つの異なる答えを出力します (これは、質問 1 の原因を考えている場合にも説明できます)。

誰かがこれに光を当てることができますか..また、誰かがこの背後にある理由を説明できれば..

どうもありがとう

4

3 に答える 3

2

最初に2番目の質問に答えます:

説明は、anintが通常4バイトであり、最上位バイトが最初の2つの位置に格納される可能性があるという事実です。shortわずか2バイトのAも、最初の2つの位置にデータを格納します。明らかに、とに格納するが65536、同じメモリ位置を指すと、データは、に対して2バイトオフセットして格納され、の最下位2バイトはのストレージに対応します。 。intshortintshortintshort

したがって、コンパイラがを出力するとき、コンパイラは*dこれをaとして解釈し、shortのストレージに対応する領域を調べますshort。これは、コンパイラが以前に65536いつ*p書き込まれたかを格納した場所ではありません。書き込み*p = 65536;によって前のが上書きされ、*d = 65536;最下位2バイトに。が入力されることに注意してください0

最初の質問について:コンパイラはforを2バイト以内に格納しません。割り当てたメモリの範囲外になるだけです。これにより、ある時点でバグが発生する可能性があります。65536*p

于 2012-04-21T19:34:47.513 に答える
1

C では、割り当ての範囲外への書き込みに対する保護はまったくありません。それをしないでください、何かが起こる可能性があります。ここでは、偶然にも、割り当てた2バイトの後ろのスペースが他の何かに使用されていないため、うまくいくようです。

于 2012-04-21T19:27:13.683 に答える
0

1)OSメモリマネージャの粒度は4Kです。1ビットのovewriteがAV/セグメンテーション違反をトリガーする可能性は低いですが、隣接する場所のデータが破損し、次の原因になります。

2)未定義の動作。この一連の動作には、「明らかに正しい操作」が含まれます(今のところ!)。

于 2012-04-21T19:33:54.090 に答える