2015-11-21 24 views
6

Ho riassunto il mio problema con il seguente breve programma.SEGFAULT in modalità -O3?

Fa SEGFAULT solo in modalità -O3 (-O2 funziona correttamente). In base a gdb, si verifica alla riga *f = 0.

#include <iostream> 

void func1(int s, int t) 
{ 
     char* buffer = new char[s + t*sizeof(float)]; 
     if (!buffer) 
     { 
      std::cout << "new failed\n"; 
      return; 
     } 
     float* f = (float*)(buffer + s); 
     for (int i = 0; i < t; ++i) 
     { 
      *f = 0; 
      //std::cout << i << std::endl; // if uncomment this line everything will work fine 
      ++f; 
     } 
     delete [] buffer; 
     std::cout << "done\n"; 
} 

int main() 
{ 
     int s = 31, t = 12423138; 
     std::cout << s << " " << t << std::endl; 
     func1(s, t); 
     return 0; 
} 

Per favore fatemi sapere, cosa sto sbagliando?

+8

Quella è una grave violazione del [rigorosa regola aliasing] (http : //stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). Per quanto riguarda il crash è probabilmente perché si accede ai dati non allineati. A causa del problema di aliasing, potrebbe non essere d'aiuto, ma provare a compilare con più avvisi (ad esempio "Wall -Wextra -pedantic") e vedere se ti dice qualcosa. –

+0

@JoachimPileborg Ho compilato questo codice su MSVC con -W4 -Wx e ha compilato correttamente. –

+1

AFAIK MSVC++ non assume mai rigide regole di aliasing e non rende le ottimizzazioni dipendenti da queste regole. –

risposta

2

La fonte di SEGFAULT non era solo in violazione della regola di aliasing rigida, poiché il problema persisteva anche con il flag -fno-strict-aliasing.

Si stava effettivamente accedendo alla memoria non allineata, ma non così semplice. Come i processori moderni, in genere consentono l'accesso alla memoria non allineato e al giorno d'oggi non c'è nemmeno un sovraccarico. Ho fatto un po 'di benchmarking e non ho notato una grande differenza nella lettura algined vs unaligned sulla mia CPU Intel (R) Xeon (R) E5-2680 v2 @ 2.80GHz. Inoltre ci sono some risultati molto simili (e più o meno recenti) nel web.

Il mio problema era che la modalità -O3 consente -ftree-vectorize bandiera, quindi, il mio ciclo è stato for vettorializzare (come ho potuto vedere Uso -ftree-vectorizer-verbose bandiera). E (AFAIU) non c'è ancora nessun supporto per l'accesso alla memoria non allineato usando le istruzioni vettorizzate , quindi c'era un'eccezione di runtime.

This article mi ha aiutato molto a capire la teoria, anche se sembra che l'accesso oggi la memoria non allineato non è così dannoso come lo era, anche se ancora difficile