問題タブ [strict-aliasing]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - ユーザーデータを使用した厳密なエイリアシングとコールバック
コールバックベースのCAPIを備えたC++ライブラリがあります。コールバックタイプは次のようになります。
ユーザーはこのようなコールバックを登録し、任意のデータへのポインターを設定でき、ライブラリはそのポインターをコールバックを介して返します。
ここでの私の主な関心事は、厳密なエイリアシングルールに違反しているかどうかです。userDataのタイプをchar*に変更する必要がありますか?
c++ - 一般的なchar[]ベースのストレージと、厳密なエイリアシングに関連するUBの回避
たくさんの型を適切な大きさのchar配列にパックし、正しく型付けされた個々の参照としてデータにアクセスできるようにするクラステンプレートを作成しようとしています。現在、標準によれば、これは厳密なエイリアシング違反につながる可能性char[]
があり、互換性のないオブジェクトを介してデータにアクセスしているため、未定義の動作につながる可能性があります。具体的には、標準は次のように述べています。
プログラムが次のタイプのいずれか以外のglvalueを介してオブジェクトの保存された値にアクセスしようとした場合、動作は未定義です。
- オブジェクトの動的タイプ、
- オブジェクトの動的タイプのcv修飾バージョン。
- オブジェクトの動的タイプに類似したタイプ(4.4で定義)、
- オブジェクトの動的型に対応する符号付きまたは符号なしの型である型、
- オブジェクトの動的型のcv修飾バージョンに対応する符号付きまたは符号なし型である型。
- 要素または非静的データメンバー(再帰的に、サブアグリゲートまたは含まれるユニオンの要素または非静的データメンバーを含む)の中に前述のタイプの1つを含む集合体または共用体タイプ。
- オブジェクトの動的型の(おそらくcv修飾された)基本クラス型である型、
char
またはunsigned char
タイプ。
強調表示された箇条書きの文言を考えると、私は次のalias_cast
アイデアを思いつきました。
(上記のテストコード、特にクラスはアイデアの単なるデモンストレーションなので、どのように使用するかData
を指摘しないでください。テンプレートもcv修飾型を処理するように拡張する必要があり、安全にしか使用できません。配置要件が満たされている場合に使用されますが、このスニペットがアイデアを実証するのに十分であることを願っています。)std::pair
std::tuple
alias_cast
このトリックはg++による警告を沈黙させ(でコンパイルした場合g++ -std=c++11 -Wall -Wextra -O2 -fstrict-aliasing -Wstrict-aliasing
)、コードは機能しますが、これは厳密なエイリアシングベースの最適化をスキップするようにコンパイラーに指示する本当に有効な方法ですか?
有効でない場合、エイリアシングルールに違反せずに、このようなchar配列ベースの汎用ストレージクラスを実装するにはどうすればよいでしょうか。
alias_cast
編集:を次のような単純なものに置き換えreinterpret_cast
ます:
g ++でコンパイルすると、次の警告が生成されます。
aliastest-so-1.cpp:'T&Data :: first()[with T=int;のインスタンス化 U = short unsigned int]':aliastest-so-1.cpp:28:16:
ここから必要ですaliastest-so-1.cpp:21:58:警告:型のパンニングされたポインターを逆参照すると、厳密なエイリアスルールが破られます[- Wstrict-aliasing]
c++ - C/C++ での共用体の malloc/new Array の解放/削除
私は働いていて、組合の利用を考えていました。設計が構造体/クラスを実際に要求したため、私はそれに反対することにしましたが、最終的に次の仮説的な質問につながります。
この不自然な例のような共用体があるとします。
. . . 次に、配列の 1 つを割り当てて、別の場所から削除してみます。
malloc の実装方法により、技術的には定義されていませんが、これは機能すると思います。また、int と float とは異なり、配列が同じサイズになる可能性は低いですが、array_c を割り当てるときにも機能すると思います。
このテストは、類似した new と delete で繰り返すことができます。これらもうまくいくと思います。
言語仕様はこれを行うことで私を嫌うだろうと推測していますが、うまくいくと思います. 「オブジェクトではなく配列であっても、void* にキャストされた new-ed ポインターを削除しないでください」ビジネスを思い出させます。
質問: 仕様はこれを行うことについて何と言っていますか? 簡単に確認しましたが、特にこのケースに対処するものは見つかりませんでした。とにかく、これは機能的な観点から見れば、どれほど賢明ではないでしょうか(私は、これが明確さの観点からひどいことだと認識しています)。
これは純粋に衒学的な目的のための好奇心の問題です。
c++ - C++ のユニオン内の 2 つの配列
次のようにユニオンで 2 つの配列を共有することは可能ですか?
これら 2 つの配列は同じメモリ サイズを共有していますか、それともどちらかが長いですか?
c++ - ユニオン: ユニオンの 1 つのデータ メンバーから読み取り、別のデータ メンバーに書き込む
以下のコードでは、下の「違法」は未定義であることを知っています (ただし、一部のコンパイラでは許可されています)。これは、ユニオン メンバー「a」がアクティブであり、次にユニオン メンバー「b」から読み取るためです。問題は、「AmILegal」のコードはそれを修正するのか、それとも何か恐ろしいこと、さらにあいまいなことをしているのかということです。memcpy を使用して同じ効果を達成できますか、それとも別の未定義の動作を呼び出していますか?
編集: たぶん、例は十分に明確ではありません。私がしたいのは、他のメンバーをアクティブにすることだけです。したがって、float を int に変更しています。ばかげているように見えますが、実際のケースに近いです。コードの下を読んでください。
(何らかの理由で、ある組合員を別の組合員にコピーすることは許可されていませんか?)
上記のすべてがあまり役に立たないと思われる場合は、a が実際には float と結合された _m128 であると考えてください[4]。ビット表現は常に正確で正確です。ある時点で、それを実際に使用する必要があり、float の配列としてメイン メモリに保持する必要があります。「コピー命令」は、実際には_m128ユニオンメンバーからfloat [4]メンバーへの_mm_store_psです。したがって、memset に関する質問 - 多分それは私が必要とするもののより正確な例です...
c - 例による制限修飾子の理解
キーワードのrestrict
動作は、C99で6.7.3.1によって定義されています。
Dを、オブジェクトPをタイプTへの制限修飾ポインターとして指定する手段を提供する通常の識別子の宣言とします。
Dがブロック内に表示され、ストレージクラスexternがない場合は、Bがブロックを示します。関数定義のパラメーター宣言のリストにDが表示されている場合は、Bが関連するブロックを示しているとします。それ以外の場合は、Bがメインのブロック(または自立環境でのプログラムの起動時に呼び出される関数のブロック)を示します。
以下では、ポインタ式Eは、(Eの評価前のBの実行のあるシーケンスポイントで)以前にポイントした配列オブジェクトのコピーを指すようにPを変更する場合、オブジェクトPに基づくと言われます。 E.119の値を変更します)'' based''は、ポインタ型の式に対してのみ定義されていることに注意してください。
Bを実行するたびに、LをPに基づく&Lを持つ任意の左辺値とします。Lが指定されたオブジェクトXの値にアクセスするために使用され、Xも(何らかの方法で)変更される場合、次の要件が適用されます。 :Tはconst-qualifiedであってはなりません。Xの値にアクセスするために使用される他のすべての左辺値も、Pに基づくアドレスを持つものとします。Xを変更するすべてのアクセスは、この節の目的のために、Pを変更することも考慮されるものとします。ブロックB2に関連付けられた別の制限付きポインタオブジェクトP2に基づくポインタ式Eの値がPに割り当てられている場合、B2の実行はBの実行の前に開始するか、B2の実行はBの実行の前に終了する必要があります。割り当て。これらの要件が満たされていない場合、動作は未定義です。
他のほとんどの人と同じように、私はこの定義のすべての複雑さを理解するのに苦労しています。この質問への回答として、4番目の段落の各要件について、要件に違反する使用法の一連の良い例を見てみたいと思います。この記事:
「コンパイラが想定するかもしれない...」という観点からルールを提示するのに良い仕事をします。そのパターンを拡張し、コンパイラーが行うことができる仮定と、それらがどのように成り立たないかを、それぞれの例で結び付けることは素晴らしいことです。
c - 制限修飾子を使用するための混乱する適応コード
stpcpy
次のバージョンの関数を、restrict
修飾されたポインターを引数として内部的に使用するように適応させようとしていますが、修飾子を追加するだけで未定義の動作が発生するかどうかはわかりません。
オブジェクトへのアクセスに関する C99 6.7.3.1 の規則が、アクセスされる個々のオブジェクトのみに関係し、配列全体には関係しないと仮定すると、書き込まれた要素は一度だけアクセスされ、書き込みのためだけにアクセスされるため、問題ないと思います。しかし、私はrestrict
この時点で使用することにかなり不快であり、自分の判断だけに頼りたくありません.
c++ - このユニオンは厳密なエイリアシングを破りますか?浮動小数点レジスタはどうですか
IEEEのちょっとしたトリックにそのユニオンを使用する必要がありますが、それは厳密なエイリアシングを破りますか?GCCは警告をスローしていません(衒学的な厳密なエイリアシングでもGCC 4.5および4.6で試しましたが、私が知る限り、GCCは厳密なエイリアシングルールの違反(多くの誤検知/ネガティブ)をうまくキャッチできません。
これは私が現在使用しているスニペットであり、警告なしで正しく機能しているように見えますが、特定のコンパイラの最適化では、副作用や未定義の動作が発生する可能性があります。したがって、そのコードが特定の条件下で安全でない可能性がある場合は、それを削除するためにいくつかの努力をします。
また、このコードでは、データを標準レジスタから最新のCPUのフローティングポインティングレジスタに移動する必要があり(これについては興味があります)、古いCPUに比べて余分なサイクルが必要になると思います。
上記のコードは最適化を意図したものではないので、最適化を悪用することを誹謗中傷しないでください。上記のコードは、特定の結果を取得するための最も簡単な方法でした(幸い、最も簡単な方法は、私の場合!)、結果が安全でない場合は、より遅い方法を使用します。
前もって感謝します
c - char へのジェネリック ポインタと厳密なエイリアシングについて
gcc
次のコードがエラーなしで正常に動作する理由がわかりません( -fstrict-aliasing -Wstrict-aliasing=1
)。
厳密なエイリアシング ルールに従うと、次のようになります。
n1570、§ 6.5 式
オブジェクトは、次の型のいずれかを持つ左辺値式によってのみアクセスされる格納された値を持つものとします。
— オブジェクトの有効な型と互換性のある型、
— オブジェクトの有効な型と互換性のある型の修飾されたバージョン
- オブジェクトの有効な型に対応する符号付きまたは符号なしの型である型、
- オブジェクトの有効な型の修飾されたバージョンに対応する符号付きまたは符号なしの型である型、
— 前述のタイプのいずれかをメンバーに含む集約型または共用体型 (再帰的に、サブ集約または含まれる共用体のメンバーを含む)、または
— 文字タイプ。
ただし、修飾されたバージョン、対応する符号付きまたは符号なしの型、文字型のいずれか*q
と互換性のある型はありません。*p
では、なぜ許可されているのでしょうか。
c++ - T*をchar*でエイリアシングできます。逆も許されますか?
注:この質問は、より焦点を絞って読みやすくするために名前が変更され、縮小されています。コメントのほとんどは古いテキストを参照しています。
標準によれば、異なるタイプのオブジェクトは同じメモリ位置を共有しない場合があります。したがって、これは合法ではありません。
ただし、この標準では、この規則の例外が許可されています。任意のオブジェクトには、char
またはへのポインタを介してアクセスできunsigned char
ます。
しかし、これが逆に許可されているかどうかは私にはわかりません。例えば: