2017-11-22 10 views
0

これはあまりにも議論の余地のない質問ではないことを願っていますが、私はSOに適切な完全な答えを見つけることができません。これはまた、reserveresizeの違い、またはcapacitysizeの違いについて、私にはっきりと分かっており、しばしば十分に尋ねられています。また、これは疑問ではありません。これが良い練習であれば、それはそうではありません。私は最初のFooと予備のメモリのstd::vectorを作成するのではなく、ベクトルのサイズを変更していないstd :: vectorの予約領域に書き込むと、セグメンテーションフォルトが発生する可能性がありますか?

#include <vector> 
#include <iostream> 

struct Foo 
{ 
    double a, b; 
}; 

int main(int argc, char* argv[]) 
{ 
    std::vector<Foo> Vec; 
    Vec.reserve(100); 

    Foo foo; 
    foo.a = -13.131; 
    foo.b = 3.141; 

    for(int i = 0; i < 100; ++i) 
    Vec[i] = foo; 

    for(int i = 0; i < 100; ++i) 
    std::cout << Vec[i].a << std::endl; 

    return 0; 
} 

は、次のような状況を考えてみましょう。明らかにsize() = 0ですが、100要素分のメモリが割り当てられており、プログラムで自由に使用できるようになりました。技術的には、これらの要素のメモリ内の任意の位置に書き込んだり読み込んだりすると、セグメンテーションフォルトが発生することはありません。

私はUbuntu 14.04でこのコードを実行しようとしましたが、すべての要素が正常に書き込まれ、すべての出力が-13.131になりました。ベクトルサイズは0のままですが、つまり、要素が初期化されていないため、実際には何らかの方法でセグメンテーションフォールトが発生する可能性があります(ベクトル内のユニット化されたポインタの要素にアクセスすることについては言及していません。 )?

hereこれは私の考えを確認しているようですが、原則としてC++のコンパイルをサポートするすべてのプラットフォームで動作しますか?

+18

未定義の動作は未定義です。 – tkausl

+6

境界を越えることは未定義の動作です。物語の終わりは本当に。 –

+0

セグメンテーションフォールトが発生したり、シェルのアクセス権の弱点を悪用したり、ハードドライブをフォーマットしたりすることがあります。また、夜間に起きて、カメの下に亀を置く可能性があります。 UBの喜びがそうです。起こっていることや起こっていないことに頼ることはできません。 – DevSolar

答えて

3

動作が定義されていないと、未定義の動作です。 定義されていない動作の重要な側面の1つは、さまざまなシステムとコンパイラで動作がどのようになるかを確認できないことです。これで、特定のコンパイラと特定のライブラリ実装のコードを見ることができ、期待通りに動作することがわかります。

しかし、私は、これがすべての異なるシステム、コンパイラ、およびライブラリ実装で機能することを喜んで願っている人はいないと思います。

たとえば、特定のベクター実装が内部情報用に予約されたメモリを使用することを決定した場合はどうなりますか?たぶんそれは起こりそうもないかもしれませんが、システムが実際にそれをやっていることをどのように確かめることができますか?

0

reserve()が呼び出されたときにメモリを割り当てますが、バックグラウンドスレッドでコピーを開始するstd :: vectorの実装を考えてみましょう。shrugs近い将来に何が起こるかを知っている人!それがコピーしている間、すべての読み込みはロックされず、古いメモリ領域にまっすぐに進みます。これは読み込みにも適しているからです。

範囲外のものを読み取ろうとすると、ランダムなメモリを読み込もうとしますが、割り当てられた新しいメモリであるとは限りません。

コメントやその他の答えによると、未定義は定義されていません。

関連する問題