厳密なエイリアシングから2つのバグがあり、すべてを修正しようと思っていました。それが何であるかを詳しく見てみると、GCCは警告を出しませんし、実装が不可能なものもあるようです。少なくとも私の理解では、以下のすべてが壊れています。私の理解は間違っているか、これらのことを行う正しい方法があるのでしょうか、あるいは技術的にルールを破ってシステムテストで十分にカバーしなければならないコードがありますか?厳密なエイリアシングは矛盾しているようです
バグは、charとunsigned charバッファが混在しているコードからのものです。以下のように:
size_t Process(char *buf, char *end)
{
unsigned char *buf2 = (unsigned char *)buf;
unsigned char *p = buf2;
unsigned char *end2 = (unsigned char*)end;
ProcessSome(&p, end2);
return (size_t)(p - buf2);
}
もあります:それはまだ、これが機能するようになりましたし、自由に警告している理由を私は確認していないキャストを必要とするが、以下にこれを変更する
size_t Process(char *buf, char *end)
{
char *p = buf;
ProcessSome((unsigned char**)&p, (unsigned char*)end);
//GCC decided p could not be changed by ProcessSome and so always returned 0
return (size_t)(p - buf);
}
は、問題を修正するように見えました警告
//contains a unsigned char* of data. Possibly from the network, disk, etc.
//the buffer contents itself is 8 byte aligned.
const Buffer *buffer = foo();
const uint16_t *utf16Text = (const uint16_t*)buffer->GetData();//const unsigned char*
//... read utf16Text. Does not even seem to ever be a warning
//also seems to work fine
size_t len = CalculateWorstCaseLength(...);
Buffer *buffer = new Buffer(len * 2);
uint16_t *utf16 = (uint16_t*)buffer->GetData();//unsigned char*
len = DoSomeProcessing(utf16, len, ...);
buffer->Truncate(len * 2);
send(buffer);
そして
...といくつかなくても動作するように見える他の場所の束であります大文字小文字の区別がありません。これには警告はありません。悪い場合でも、どうすれば回避できますか(どちらもうまくいくようです)?
int *x = fromsomewhere();//aligned to 16 bytes, array of 4
__m128i xmm = _mm_load_si128((__m128*i)x);
__m128i xmm2 = *(__m128i*)x;
は、他のAPIのを見るだけでなく私の理解で、ルールに違反していることを様々なケースがあるようです(Linuxでは/ GCC specfic 1に遭遇していませんが、必ずどこかに1が存在することになります)。
CoCreateInstance明示的なポインタキャストを必要とするvoid **出力パラメータがあります。 Direct3Dにも同様のものがあります。
LARGE_INTEGERは、異なるメンバーへの読み書きが可能な組み合わせです(たとえば、一部のコードが高低を使用している可能性があり、他のコードがint64を読み取る可能性があります)。
私が見たハッシュ実装の多くは、入力バッファをuint32_t *にキャストし、おそらくuint8_tを使用して最後に1-3バイトを処理します。
私が見たほとんどのメモリアロケータの実装は、char *またはunsigned char *を使用していますが、必要な型にキャストする必要があります(返されたvoid *を使用していますが、 )
私は、CPythonの実装が非常にうまくいけば、最初に同じメモリレイアウトを持つ他のものにPyObject *をキャストすることを思い出してください。
は、実際にあなたの最初の例をい常にゼロを返すという振る舞いを呈しますか、それともコードに似ていますか?私はその行動を再現できませんでした。 –
かなり正確には、ちょうど異なる関数名です。これは、x64を対象とした変更された企業の赤い帽子でgcc 4.4.5でした。しかし、全体のロットがインライン化されているので、GCCがどのように全体を最適化するかということに非常に特化しているかもしれません。 – Will