0

以下のコードは私にとってはうまくいきます。これはどのように機能しますか?これはセグメンテーション違反ではありませんか?

char * buffer = new char[100];
float * in_buf = new(buffer) float[100];

また、私はこのようなクラスを取得しました:

class Item
{
public:
   Item(int num)
   {
     u = new float[num];
     v = new float[num];
   }
   float * u;
   float * v;
   //And many other variables
}

メモリのブロックを作成し、その中に v と u を割り当てたいと思います。このアプローチは安全ですか?

class Item
{
public:
   Item(int num)
   {
     buffer = new char[(sizeof(char)+2*sizeof(float))*num];
     u = new (buffer) float[num];
     v = new (buffer+sizeof(float)*num) float[num];
   }
   char * buffer;
   float * u;
   float * v;
   //And many other variables
}
4

4 に答える 4

3

以下のコードは私にとってはうまくいきます。これはどのように機能しますか?これはセグメンテーション違反ではありませんか?

char* buffer = new char[100];
float* in_buf = new(buffer) float[100];  

「作品」とはどういう意味ですか?ここでのnews は、問題のデータ型を初期化/構築する必要がないため、それらに使用することを暗黙的に計画しているメモリからの読み取りまたは書き込みを (必ずしも) トリガーしません。したがって、segfault が表示されない理由の 1 つは、コードが実質的にこれを行うだけであるということです。

char* buffer = new char[100];
float* in_buf = reinterpret_cast<float*>(buffer);

ala の読み取りまたは書き込みに進むとin_buf[99] = 2;、segfault が発生する可能性が高くなりますが、保証にはほど遠いです。そのアドレスのメモリがアプリケーションの仮想アドレス空間にある可能性があります。たとえば、100 文字の要求がメモリの 1 ページの要求によって満たされ、OS ページ サイズが >= 4096 バイトであるとします。1000 個の 4 バイト浮動小数が偶然に適合するか、以前のnewおよびdeleteが既にメモリをマップしていたためです。実際にすぐに segfault にならなかったとしても、いつの日かヒープやその他のヒープにホストされたデータをクラッシュまたは破損させる可能性があります。より一般的に言えば、C++ で実行できる安全でないことはたくさんありますが、実際にはすぐに噛み付くわけではありません....

これは安全ですか?

buffer = new char[(sizeof(char)+2*sizeof(float))*num];
u = new (buffer) float[num];
v = new (buffer+sizeof(float)*num) float[num];

はい (num の適切な値を仮定すると)、しかしそれは無意味に複雑です (そして余分な文字は無意味で積極的に混乱を招きます)。あなたは単に行うことができます:

u = new float[2 * num];
v = &u[num];
于 2012-07-24T02:40:25.263 に答える
3
  1. 2 番目のステートメントは潜在的な UB です ( buffer100 のバックストレージとして使用してfloatおり、確実に 100 より多くのメモリを使用していますchar)。それでも、スカラー型に対するデフォルトのアクションはそれらを初期化しないままにすることであるため、UBについては完全にはわかりませんnew。そのため、そのステートメントで実際にメモリは触れられません。

  2. 確かにできますが、それは役に立たない過度の複雑さです。単純なnew. 配置newはごくまれな場合にのみ存在することに注意してください。通常は使用しないでください。

于 2012-07-24T00:40:00.780 に答える
1

最初の質問の問題は、非常に小さな変更で説明できるため、コードを並べて比較しないとわかりません。

char * buffer = new char[100];
float * in_buf = new(buffer) float[100]();

これにより、MSVS でランタイム ヒープ破損エラーが発生します。

于 2012-07-24T00:59:01.890 に答える
0

他の回答が述べたように、行float * in_buf = new(buffer) float[100];は配列のほとんどを の境界を超えていますbuffer。メモリにはまだ触れていないため、セグメンテーション違反ではありません。

u と v に意味のあるコンストラクターがない場合 (つまり、ゼロで初期化されている場合)、配置 new は意味がなく、次のようなものほど明確ではありません。

class Item
{
public:
    Item(int num)
    {
        size_t buffer_size = sizeof(*buffer);
        size_t u_size = sizeof(*u) * num;
        size_t v_size = sizeof(*v) * num;
        buffer = new char[buffer_size + u_size + v_size];
        u = reinterpret_cast<float* >(buffer + buffer_size);
        v = reinterpret_cast<float* >(buffer + buffer_size + u_size);
    }
    char * buffer;
    float * u;
    float * v;
    //And many other variables
};

num実行時パラメータが必要ですか? あなたがそれをやり遂げることができれば、私は Item を次のようにテンプレート化することをお勧めします:

template <int NUM>
class Item
{
public:
    Item() {}
    char buffer[NUM];
    float u[NUM];
    float v[NUM];
    //And many other variables
};
于 2012-07-24T02:52:34.067 に答える