0

私は CLHEP ライブラリを使用していますが、いくつかの問題に遭遇しました。これらの変更の前に、私は粒子運動量のセットを CLHEP オブジェクトのベクトル (std::vector) として生成し、これらを別のプログラム (MadGraph) が使用するために、同じ運動量を含む通常の配列のベクトルに変換していました。この変換ルーチンを新しい関数に入れたかったので、これを作成しました。

std::vector<double*> MadGraphConvert(vector<CLHEP::HepLorentzVector> p) {

double ptemp[6][4];

for (int i = 0; i < 6; i++) {
    ptemp[i][0] = p.at(i).e();
    ptemp[i][1] = p.at(i).x();
    ptemp[i][2] = p.at(i).y();
    ptemp[i][3] = p.at(i).z();
}

// Give particles to MG in a 'vector of arrays' format
std::vector<double*> p_MG;

p_MG.push_back(ptemp[0]);
p_MG.push_back(ptemp[1]);
p_MG.push_back(ptemp[2]);
p_MG.push_back(ptemp[3]);
p_MG.push_back(ptemp[4]);
p_MG.push_back(ptemp[5]);

return p_MG;
}

コードを実行すると、この他のコードで何かがセグメンテーション違反をスローしますが、以前に持っていたものを渡していると思いますか? 私の古い変換セットは次のようになりました。

    p[0][0] = pa.e();
    p[0][1] = pa.x();
    p[0][2] = pa.y();
    p[0][3] = pa.z();

    p[1][0] = pb.e();
    p[1][1] = pb.x();
    p[1][2] = pb.y();
    p[1][3] = pb.z();
.
'
'
    std::vector<double*> p_MG;

    p_MG.push_back(p[0]);
    p_MG.push_back(p[1]);
    p_MG.push_back(p[2]);
    p_MG.push_back(p[3]);
    p_MG.push_back(p[4]);
    p_MG.push_back(p[5]);

これら 2 つのアプローチの違いを誰かが見つけられたら、私はとても感謝しています! 乾杯ジャック

4

1 に答える 1

4

には、関数が戻るときに範囲外にあるローカル変数 array からのvectorアドレスが取り込まれているため、ダングリング ポインターが含まれています。ダングリング ポインターの逆参照は未定義の動作です。この場合、セグメンテーション違反が発生します。ptempMadGraphConvert()

std::vector<std::vector<double>>代わりにaを使用します。

std::vector<std::vector<double>> ptemp(6, std::vector<double>(4));

forループはそのまま機能し (このコンストラクターは、各要素が 4 つの s の別の要素である 6 つの要素で を作成するため) vectorvector単にdouble戻りptempます ( の戻り値を変更することを忘れないでくださいMadGraphConvert())。


この回答にコメントされているように、型の変更が禁止されている場合は、double[4]を使用して配列を動的に割り当てnewます。がアレイを所有するようになり、不要になったときにvectorアレイを所有する必要があります。delete[]

// In function.
std::vector<double*> ptemp(6); // By default, created with six null pointers.
try
{
    for (size_t i(0), count(ptemp.size()); i < count; i++)
    {
        ptemp[i] = new double[4];
        // Remainder of loop as before.
    }
}
catch (std::exception const&) // std::out_of_range, std::bad_alloc
{
    // Exception safety.
    // delete[] whatever was allocated, remember that
    // delete[] on a null pointer is a no-op so no
    // prior check required.
    for (auto i : ptemp) delete[] i;
    throw;
}

そしてただ戻るptemp。その後、vector不要になった場合:

// c++11
for (auto i : ptemp) delete[] i;

// c++03
for (std::vector<double*>::iterator i(ptemp.begin());
     i != ptemp.end();
     i++)
{
    delete[] (*i);
}
于 2013-03-04T12:39:43.193 に答える