2011-11-22 1 views
6

これはかなりこじつけですが、次のコードは、「安全な」(つまり、セグメンテーションフォールトが発生しないことが保証)です:std :: vector :: reserve safeの後に生ポインタにアクセスしていますか?

std::vector<int> vec(1); // Ensures that &vec[0] is valid 
vec.reserve(100); 
memset(&vec[0], 0x123, sizeof(int)*100); // Safe? 

私は、これは醜いであることを認識 - 私はそれが技術的に安全ですかどうかを知るためにのみ興味、 "きれい"ではありません。私はその唯一の用法は、指定されたインデックスを超えて格納された値を無視することができると思う。

注! How can I get the address of the buffer allocated by vector::reserve()?は同じトピックをカバーしていますが、これがの安全な場合はであり、これに落とし穴がある場合はもっと興味があります。

EDIT:オリジナルコードが間違っていました。元のmemcpymemsetに置き換えました。

+1

これは醜いので、痛いです。どうしてそんなことをするのか?あなたが本当にしなければならない場合、単に配列を使用することはできませんか?この例では100が固定されているため、[]を削除しなくてもスタック上の配列を使用することができます。 – Francesco

+2

"Segmentation fault"はプラットフォーム固有のイベントです。 C++言語は、それが何であるかを記述していません。言葉は、何かが定義されているかどうか、そうであれば、何をするかだけを言います。 –

+1

私は質問を落としましたが、それは悪い質問ではありませんが、あなたが求めていたことがあなたが求めていたものであることを保証するのに十分な時間がかからなかったからです(元のコードと現バージョンのコードはかなりです異なる)。-2ポイントはそれほど高くはありませんが、他の人に援助しようと答える時間を取るように、後で質問を再調整すると無駄になるのはその時ですに。 –

答えて

16

いいえ、安全ではありません。

reserve()の後、capacity()に達するまで、ベクトルはストレージを再割り当てしないことが保証されます。

しかし、標準では、size()capacity()の間の格納でベクトルの実装が何を行うことができるのかについては言及していません。おそらく、それはいくつかの内部データのために使用することができます - 誰が知っていますか?おそらく、アドレス空間は予約されていて実際のRAMにマップされていないのでしょうか?

[0..size]以外の要素にアクセスすることは、未定義の動作です。そこではになる可能性があります。

+0

が指摘されていましたが、これは悪い考えです。予約されたメモリはUBで、 'resize'dまたは' push'/'emplace'dするまで、ベクトルを介して '正式に'利用できません。 –

2

ベクトル-再配分は再配分(23.3.6.2を、[vector.capacity])引き起こす可能性が既存ポインタ、参照など準備を無効にしていますが最終的な再配分後の最初の要素のアドレスを取っています(この場合はまったく起こりませんが、その点以外にもあります)。だから私はコードに問題はないと思う。

+0

memcpyではなくmemsetを使用するように私の質問を更新しました(私の例は間違っていました)。 – larsmoa

2

最初に、memset0x123を1バイトに切り捨て、4バイトのパターンを書き込まずに書き込むことに注意してください。しかし、コンパイラが何のために割り当てられたスペースを使用しない場合はPODのタイプのために特別に機能するように見えることがあり、質問に答えるためにstd::vector<int> vec(100, whatever_value_you_want);

すると、ちょうどコンテナを使用する、ことをいたしません。もし誰かがresizeinsertpush_backなどと呼んでいれば、既にあなたが書いたものをメモリに吹き飛ばすでしょうし、ベクトルのサイズも間違っています。そのようなコードを書く理由はない。

関連する問題