Gcc'nin C'deki bazı ifadeleri optimize etmesini nasıl önleyebilirim?


107

Bir sayfayı kirletmek için (sayfa tablosu girişindeki kirli biti açmak), sayfanın ilk baytlarına şu şekilde dokunuyorum:

pageptr[0] = pageptr[0];

Ancak pratikte gcc, ölü depo eleme yoluyla bu ifadeyi yok sayacaktır. Gcc'nin onu optimize etmesini önlemek için ifadeyi aşağıdaki gibi yeniden yazıyorum:

volatile int tmp;
tmp = pageptr[0];
pageptr[0] = tmp;

İşe yarıyor gibi görünüyor, ama biraz çirkin. Aynı etkiye sahip herhangi bir yönerge veya sözdizimi var mı bilmek isterim? Ayrıca -O0büyük bir performans cezası getireceği için bayrak kullanmak istemiyorum .


8
@Mark -O0 optimizasyonu durdurur, ancak aynı zamanda program performansını da yavaşlatır. Sadece bu kod pasajının optimizasyonunu önlemek istiyorum: P
ZelluX

Eklemek isterim ki, geçmişte kullanmak bile -O0ölü kod "optimizasyonu" nu engellemedi, örneğin, GCC bazı kodların hiçbir etkisi olmadığını tespit ettiğinde, basitçe kaldırır. AFAIK bu daha önce bir aşamadır -O0... Ama bu sadece benim deneyimim
smoothware

Yanıtlar:


91

Optimizasyonu kapatmak sorunu düzeltir, ancak gereksizdir. Daha güvenli bir alternatif, derleyicinin volatiletür niteleyicisini kullanarak depoyu optimize etmesini yasa dışı yapmaktır .

// Assuming pageptr is unsigned char * already...
unsigned char *pageptr = ...;
((unsigned char volatile *)pageptr)[0] = pageptr[0];

volatileDerleyici bildirir tip eleme bellek mağazaları ve yükleri konusunda katı olması. Bir amacı volatile, derleyiciye bellek erişiminin yan etkileri olduğunu ve bu nedenle korunması gerektiğini bildirmektir. Bu durumda, deponun bir sayfa hatasına neden olma yan etkisi vardır ve derleyicinin sayfa hatasını korumasını istersiniz.

Bu şekilde, çevreleyen kod hala optimize edilebilir ve kodunuz, GCC'yi #pragmaveya __attribute__sözdizimini anlamayan diğer derleyiciler tarafından taşınabilir .


2
Optimizasyonları kapatmak yerine bunun daha iyi olduğunu söyleyebilirim. Bu yöntemi kullanarak diğer optimizasyonlardan yine de yararlanabilirsiniz.
Ben S

3
Dietrich Epp'in çözümü ARM4.1 derleyicisi altında çalışmıyor . ZelluX'un çözümü bile çalışmıyor. ARM4.1 ZelluX çözeltisi, make 'olduğu için alternatif yöntem bu işi yapmak için sıcaklığında ' bir küresel uçucu değişken .
Oculus Dexter

1
Söz konusu derleyici için oldukça kötü.
Alexey Frunze

1
@Shocker: GCC, gerçek bellek erişimini optimize etmeden değişkeni optimize edebilir. Bunlar farklı sorunlar.
Dietrich Epp

2
@jww: bu kullanım, blog gönderisinde anlatılanlara uyuyor. volatilehafıza erişiminin yazıldığı gibi gerçekleşmesi gerektiği anlamına gelir, bu tam olarak istediğimiz şeydir. Başka bir deyişle, onu dikkatlice düşündük ve ne anlama geldiğini düşündüğümüz anlamına geliyor.
Dietrich Epp

184

Kullanabilirsiniz

#pragma GCC push_options
#pragma GCC optimize ("O0")

your code

#pragma GCC pop_options

GCC 4.4'ten beri optimizasyonları devre dışı bırakmak için.

Daha fazla ayrıntıya ihtiyacınız varsa GCC belgelerine bakın.


3
Bununla birlikte, bunun belirli ifadelerde değil, yalnızca tüm işlevler üzerinde çalıştığını belirtmek gerekir: gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/… "Bu noktadan sonra tanımlanan her işlev, öznitelik (( optimize ("STRING"))) bu işlev için belirtildi. ".
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

134

Yeni pragmaları kullanmak yerine __attribute__((optimize("O0")))ihtiyaçlarınız için de kullanabilirsiniz . Bu, aynı dosyada tanımlanan tüm işlevleri değil, yalnızca tek bir işleve uygulama avantajına sahiptir.

Kullanım örneği:

void __attribute__((optimize("O0"))) foo(unsigned char data) {
    // unmodifiable compiler code
}

3
Bir -Olevelseçeneği kullanmıyorsam ama ayrı olarak açtığı bireysel seçenekleri kullandıysam ne olur? (Benim durumumda, kodu kıran bireysel optimizasyon seçeneğinin hangisi olduğunu belirleyemiyorum) .
user2284570
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.