2

longこれは aを toにキャストする正しい方法void *ですか? -O2プログラムで使用するとセグメンテーション違反が発生しQtます。を使用するとセグメンテーション違反になりません-O1

使用するreinterpret_cast<void *>(tp.tv_nsec)と、 を使用してセグメンテーション違反も発生し-O2ます。

なぜセグメンテーション違反があるのですか?

timespec tp; // struct that holds nanoseconds since Epoch
clock_gettime(CLOCK_REALTIME, &tp); // tv_nsec is a long int

void *test = mmap((void *)(tp.tv_nsec), 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

printf("%p\n", test);
printf("%li\n", (long)test);

編集:私の知る限り、目的は間違って表現されているようです。目的は、ランダムなメモリ アドレスを割り当てるために乱数を取得することです。そうすれば、テスト プログラム全体で mmap() を何度も使用して、mmap() に乱数を供給するたびに、ランダムなメモリ アドレスを取得できます。そうでない場合、mmap() はメモリを順番に割り当てているようです。

4

4 に答える 4

2

tp.tv_nsecはアドレスではないため、キャストは無効です:

mmap((void *)(tp.tv_nsec), 4096,
                 ^ 
                 |  is not an address

これを試して:

mmap((void *) &(tp.tv_nsec), 4096,
              ^
              |  amperson operator for address

&is Address (of operand) operator は変数のアドレスを指定します

于 2013-07-06T13:59:24.313 に答える
0

変数をアドレス変数にキャストする理由は不思議ではありませんが、最適化設定の1つがこれに反対しています:

-O2 は、-O で指定されたすべての最適化フラグをオンにします。また、次の最適化フラグをオンにします。

      -fthread-jumps 
      -falign-functions  -falign-jumps 
      -falign-loops  -falign-labels 
      -fcaller-saves 
      -fcrossjumping 
      -fcse-follow-jumps  -fcse-skip-blocks 
      -fdelete-null-pointer-checks 
      -fdevirtualize 
      -fexpensive-optimizations 
      -fgcse  -fgcse-lm  
      -fhoist-adjacent-loads 
      -finline-small-functions  ----------> Result: this is causing the segfault(elaine has found so +1 to him please).
      -findirect-inlining 
      -fipa-sra 
      -foptimize-sibling-calls 
      -fpartial-inlining 
      -fpeephole2 
      -fregmove 
      -freorder-blocks  -freorder-functions 
      -frerun-cse-after-loop  
      -fsched-interblock  -fsched-spec 
      -fschedule-insns  -fschedule-insns2 
      -fstrict-aliasing                 --------> I thought this was issue(void * from long) but is not
      -fstrict-overflow 
      -ftree-switch-conversion -ftree-tail-merge 
      -ftree-pre 
      -ftree-vrp

私は疑った:

-fstrict-aliasing コンパイラが、コンパイルされる言語に適用可能な最も厳密なエイリアシング規則を想定できるようにします。C (および C++) の場合、式のタイプに基づいて最適化が有効になります。特に、あるタイプのオブジェクトは、タイプがほとんど同じでない限り、別のタイプのオブジェクトと同じアドレスに存在することは決してないと見なされます。たとえば、unsigned int は int にエイリアスできますが、void* または double にはエイリアスできません。文字型は、他のどの型にも別名を付けることができます。

私は間違っていました、恥ずかしいです。

 >:c

エレインが言ったことによると、 -finline-small-functions が問題の原因です。

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

于 2013-07-06T14:01:26.540 に答える
0

構造を使用すると、時間reinterpret_cast<void *>(tp.tv_nsec)がかかり、ポインターとして解釈されます。これにより、誤ったメモリアクセスが発生します。そのアドレスを取得して、次のようにキャストする必要があります。void*reinterpret_cast<void *>(&tp.tv_nsec)

于 2013-07-06T13:58:44.810 に答える
0

答えは C の場合ですが、C++ の場合も同様だと思います。整数型からポインターへの変換は、幅が異なり、ポインターがセグメント化されている可能性があるため、すべての場合に機能するとは限りません。あなたのプラットフォームでこれが機能する整数型がある場合は、それを にtypedef編集する必要がある[u]intptr_tため、そのような厄介なことをする必要がある場合は、その型を使用してください。

次に、mmapそのように行われることがまったく予見されていないものを使用しています。アドレスを渡す場合、これがアドレス空間で使用する有効なアドレスであることを確認するのはあなたの義務です。たとえば、ページ サイズの倍数である必要がありますが、他の制限が適用される場合があります。呼び出しの戻り値をチェックして、mmap成功したかどうかを確認します。

まず、システムに付属のドキュメントを読むことをお勧めします。man mmapあなたの友達です。

于 2013-07-06T14:47:02.893 に答える