Derleyicinin yerel bir uçucuyu sabit olarak katlamasına izin veriliyor mu?


25

Şu basit kodu düşünün:

void g();

void foo()
{
    volatile bool x = false;
    if (x)
        g();
}

https://godbolt.org/z/I2kBY7

Potansiyel çağrıyı ne görebilir, ne gccde clangoptimize edebilirsiniz g. Bu benim anlayışım için doğru: Soyut makine volatiledeğişkenlerin herhangi bir anda değişebileceğini varsaymaktır (örneğin donanım eşlemeli olması nedeniyle), bu nedenle falsebaşlatmayı ifkontrole sürekli katlamak yanlış olur.

Ancak MSVC, çağrıyı gtamamen ortadan kaldırır (okumaları ve yazmaları yine de volatilesaklayın!). Bu standartlara uygun davranış mı?


Arka plan: Zaman zaman bu tür bir yapıyı hata ayıklama çıktısını anında açıp kapatabilmek için kullanıyorum: Derleyici her zaman bellekten değeri okumalıdır, bu nedenle hata ayıklama sırasında bu değişkenin / belleğin değiştirilmesi kontrol akışını buna göre değiştirmelidir. . MSVC çıktısı değeri yeniden okur ancak elbette burada niyetlerimi yenen değeri (muhtemelen sabit katlama ve / veya ölü kod eliminasyonu nedeniyle) yok sayar.


Düzenlemeler:

  • Okuma ve yazma işlemlerinin kaldırılması volatileburada tartışılmıştır: Bir derleyicinin yerel değişken değişkenini optimize etmesine izin veriliyor mu? (teşekkürler Nathan!). Bence bu standart, bu okuma ve yazma işlemlerinin olması gerektiği kadar açık . Ancak bu tartışma, derleyicinin verilen okumaların sonuçlarını almasının ve buna göre optimize etmesinin yasal olup olmadığını kapsamaz . Sanırım bu standartta yetersiz / belirtilmemiş , ama biri beni yanlış kanıtlarsa mutlu olurum.

  • Tabii ki xyan adım için yerel olmayan bir değişken yapabilirim . Bu soru daha çok meraktan çıkıyor.


3
Bu benim için çok açık bir derleyici hatası gibi görünüyor.
Sam Varshavchik

1
Bildiğim kadarıyla bu kural gibi yasal. Derleyici, nesne değişken olsa bile, durumunun değiştirilebilmesi için bir yol olmadığını ve böylece katlanabileceğini kanıtlayabilir. Bunu cevaplayacağımdan emin değilim, ama doğru olduğunu hissediyorum.
NathanOliver

3
Ama bence OP'nin değişkenin bir hata ayıklayıcı tarafından değiştirilebileceği iddiası makul. Belki birisi MSVC ile bir hata raporu hazırlamalıdır.
Brian

2
@curiousguy Sonucu atabilir ve / veya kesin değeri alsanız bile, yine de okumuş olursunuz.
Tekilleştirici

2
İlginçtir, bunu sadece x64 için yapar. X86 sürümü hala g () godbolt.org/z/nc3Y-f adını veriyor
Jerry Jeremiah

Yanıtlar:


2

Bence [intro.execution] (paragraf numarası değişir) MSVC davranışını açıklamak için kullanılabilir:

Otomatik saklama süresine sahip her nesnenin bir örneği, bloğundaki her bir girişle ilişkilendirilir. Böyle bir nesne vardır ve bloğun yürütülmesi sırasında ve blok askıya alınırken son saklanan değerini korur ...

Standart, bir uçuculuk değerinin okunmasıyla ortadan kaldırılmasına izin vermez, ancak yukarıdaki paragrafın değerin tahmin edilmesine izin verdiği şeklinde yorumlanabilir false.


BTW, C Standardı (N1570 6.2.4 / 2) diyor ki

Bir nesne vardır, sabit bir adrese sahiptir ve son saklanan değerini kullanım ömrü boyunca korur. 34


34) Uçucu bir nesne söz konusu olduğunda, son mağazanın programda açık olması gerekmez.

C bellek / nesne modelinde otomatik depolama süresine sahip bir nesneye açık olmayan bir mağaza olup olmadığı belirsizdir.


Derleyicinin, hedef platformda müstehcen olmayan mağazaların ne zaman mümkün olduğunu bildiğini kabul edin
MM

1
Eğer bu doğruysa, yerel uçucu nesneler (en azından MSVC'de) tamamen anlamsızdır? volatileOptimizasyon amacıyla yok sayılırsa, (ek okuma / yazma dışında) satın alma ekleyen bir şey var mı ?
Max Langhof

1
@MaxLanghof Tamamen anlamsız ve istediğiniz / beklediğiniz etkiye sahip olmayanlar arasında bir fark var.
Deduplicator

1
@MaxLanghof Kayan nokta hesaplamalarının ara sonuçları bazen 80 bitlik bir kayda yükseltilerek hassas sorunlara neden olur. Bunun bir gcc-izm olduğuna inanıyorum ve bu tür çiftleri uçucu olarak ilan ederek önlendi. Bkz. Gcc.gnu.org/bugzilla/show_bug.cgi?id=323
ForeverLearning

1
@philipxy PS Cevabımı görün Erişimin uygulama tarafından tanımlandığını biliyorum. Soru erişimle (nesneye erişilir) değil, değerin tahminiyle ilgilidir.
Dil Avukatı

2

TL; DR Derleyici her uçucu erişimde ne isterse yapabilir. Ancak belgelerin size söylemesi gerekir. - "Uçucu bir glvalue aracılığıyla erişimin semantiği uygulama tarafından tanımlanmıştır."


Standart, bir uygulamanın "olduğu gibi 'kuralına" uyması gereken "geçici erişim" ve diğer "gözlemlenebilir davranış" ("yan etkiler" yoluyla elde edilen) dizilerine izin verir.

Ama standart diyor ki (benim cesur vurgu):

Çalışma Taslağı, Programlama Dili Standardı C ++
Belge Numarası: N4659
Tarih: 2017-03-21

§ 10.1.7.1 CV elemeleri

5 Uçucu bir glvalue aracılığıyla erişimin anlambilimi, uygulama tanımlıdır. [...]

Benzer şekilde etkileşimli cihazlar için (benim kalın yazı vurgulamam):

§ 4.6 Program yürütme

5 İyi biçimlendirilmiş bir programı yürüten uygun bir uygulama, aynı makineye ve aynı girdiye sahip soyut makinenin karşılık gelen örneğinin olası uygulamalarından biriyle aynı gözlemlenebilir davranışı üretecektir. [...]

7 Uygun bir uygulamaya ilişkin en az gereksinimler şunlardır:

(7.1) - Uçucu glvalues ​​yoluyla erişim kesinlikle soyut makinenin kurallarına göre değerlendirilir.
(7.2) - Program sona erdirildiğinde, dosyalara yazılan tüm veriler, programın soyut semantiğe göre yürütülmesinin olası sonuçlarından biriyle aynı olacaktır.
(7.3) - Etkileşimli cihazların giriş ve çıkış dinamikleri, bir program giriş için beklemeden önce çıkış isteminin gerçekte verildiği şekilde gerçekleşmelidir. Etkileşimli bir cihazı oluşturan şey uygulama tanımlıdır.

Bunlara toplu olarak programın gözlemlenebilir davranışı denir . [...]

(Her neyse , bir program için hangi özel kodun üretildiği standart tarafından belirtilmez.)

Standart her ne kadar uçucu erişimlerin soyut makine yan etkilerinin soyut dizilerinden ve bazı kodların (belki de) tanımladığı gözlemlenebilir davranışlardan kaynaklanamayacağını söylese de, hiçbir şeyin nesne koduna veya gerçek dünyaya yansımasını bekleyemezsiniz. derleyici belgeleriniz size geçici bir erişimin neyi oluşturduğunu söylemedikçe . Etkileşimli cihazlar için Ditto.

Eğer uçucu karşısındaki ilgilenen varsa soyut makine yan etkileri ve / veya buna bağlı gözlenebilir davranışların soyut dizileri bazı kod (belki) tanımlar olduğunu sonra bunu söylemek . Ancak, karşılık gelen nesne kodunun üretilmesiyle ilgileniyorsanız, bunu derleyici ve derlemeniz bağlamında yorumlamanız gerekir .

Kronik olarak insanlar yanlış bir şekilde uçucu erişim için soyut bir makine değerlendirmesinin / okumanın uygulamalı bir okumaya ve soyut bir makine atamasının / yazımının uygulamalı bir yazmaya neden olduğuna inanırlar. Bu inancın bulunmadığı uygulama belgelerinin böyle bir dayanağı yoktur. / İff uygulaması aslında bir "geçici erişim" üzerine bir şey yaptığını söylediğinde , insanlar bir şeyin - belki de belirli nesne kodunun oluşturulmasını beklemede haklıdır.


1
Demek istediğim, bu "tüm belirtilen yan etkilerin op olmadığı bir makine bulursam, o zaman her programı no-op'a derleyerek yasal bir C ++ uygulamam var" diye kaynar . Elbette pratikte gözlemlenebilir etkilerle ilgileniyoruz, çünkü soyut makine yan etkileri totolojik olarak soyut. Bu bazı temel yan etkileri kavramını gerektirir ve ben "geçici erişim açık bellek erişim talimatları yol açar" bunun bir parçası olduğunu (standart umurumda olmasa bile), bu yüzden gerçekten satın almayın "demek msgstr "eğer soyut anlambilim yerine kod istiyorsanız". Yine de +1.
Max Langhof

Evet, uygulama kalitesi önemlidir. Bununla birlikte, dosyalara yazma dışında, "gözlemlenebilir" [sic] uygulama tanımlıdır. Eğer set kesme noktaları, erişim belirli fiili belleğe muktedir olmasını istiyorsanız uçucu soyut üzerinde vb göz ardı 'uçucu' okur ve daha sonra yazar çıkış uygun koduna derleyici yazar almak zorunda . PS C ++ "yan etki" kendi başına gözlemleme davranışı için kullanılmaz, alt ifadelerin kısmi sıra değerlendirmesini açıklamak için kullanılır.
philipxy

[Sic] 'i açıklamak ister misiniz? Hangi kaynaktan alıntı yapıyorsunuz ve hata nedir?
Max Langhof

Yani sadece gözlemlenebilir soyut bir makinenin sadece gerçeklemenin gözlemlenebilir olduğu ve nasıl uygulandığı söylendiğinde gözlemlenebilir olduğunu kastediyorum.
philipxy

1
Bir uygulamanın etkileşimli bir aygıt diye bir şey olmadığını iddia edebileceğini mi söylüyorsunuz, bu nedenle herhangi bir program her şeyi yapabilir ve yine de doğru olur mu? (Not: Etkileşimli cihazlara vurgu yaptığınızı anlamıyorum.)
curiousguy

-1

Çeki atlamanın yasal olduğuna inanıyorum.

Herkesin alıntı yapmayı sevdiği paragraf

34) Uçucu bir nesne söz konusu olduğunda, son mağazanın programda açık olması gerekmez

bir uygulamanın bu tür mağazaların herhangi bir zamanda veya herhangi bir değişken değişken için mümkün olduğunu varsayması gerektiği anlamına gelmez. Bir uygulama hangi mağazaların mümkün olduğunu bilir. Örneğin, bu tür örtülü yazma işlemlerinin yalnızca aygıt kayıtlarına eşlenen değişken değişkenler için olduğunu ve bu eşlemenin yalnızca harici bağlantılı değişkenler için mümkün olduğunu varsaymak tamamen mantıklıdır. Veya bir uygulama, bu tür yazma işlemlerinin yalnızca sözcük boyutlu, sözcük hizalamalı bellek konumlarında gerçekleştiğini varsayabilir.

Bunu söyledikten sonra, MSVC davranışının bir hata olduğunu düşünüyorum. Aramayı optimize etmek için gerçek dünyaya gerek yok. Bu tür bir optimizasyon uyumlu olabilir, ancak gereksiz yere kötüdür.


Neden kötü olduğunu açıklayabilir misin? Kod gösterimlerinde, işlev tam anlamıyla hiçbir zaman çağrılamaz.
David Schwartz

@DavidSchwartz Yalnızca yerel değişken değişkenlerin anlambilimini belirledikten sonra sonucuna varabilirsiniz (yukarıdaki alıntılanan paragrafa bakın). Kendisi standart notlar volatilegerekiyordu değer uygulanmasına vasıta bilinmeyen tarafından değişebileceğini uygulanmasına bir ipucu olması.
Max Langhof

@MaxLanghof Uygulamanın bilinmeyen bir şeyi doğru şekilde işleyebilmesinin hiçbir yolu yoktur. Yararlı platformların aslında yaptığı, volatileo platformda ve bu spesifikasyonun dışında neler kullanabileceğinizi ve kullanamayacağınızı belirtmektir, her zaman saçma bir çekim olacaktır.
David Schwartz

@DavidSchwartz Tabii ki - soyut makinenin anlambilimini (özellikle, okuma ve yazma) takip ederek. Doğru şekilde optimize edemeyebilir - standardın noktası budur. Şimdi, bu bir nottur ve bu nedenle normatif değildir ve her ikimizin de söylediğimiz gibi, uygulama ne volatileyapacağını belirtebilir ve buna bağlı kalabilir . Demek istediğim , kodun kendisi (C ++ standart / soyut makineye göre) gçağrılabilir olup olmadığını belirlemenize izin vermiyor .
Max Langhof

@DavidSchwartz Kod böyle bir şey göstermez, çünkü örtük yazmaların olmaması koddan sonra gelmez.
n. 'zamirler' m.
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.