Neden ölü kod tespiti bir derleyici tarafından tam olarak çözülemiyor?


192

C veya Java'da kullandığım derleyicilerde ölü kod önleme var (bir satırın yürütülmediği zaman uyarı). Profesörüm bu sorunun derleyiciler tarafından asla tam olarak çözülemeyeceğini söylüyor. Bunun neden olduğunu merak ediyordum. Teori temelli bir sınıf olduğu için derleyicilerin gerçek kodlamasına pek aşina değilim. Ama neyi kontrol ettiklerini (olası giriş dizeleri ile kabul edilebilir girişler vs) ve bunun neden yetersiz olduğunu merak ediyordum.


91
bir döngü yapın, arkasından kod koyun, ardından en.wikipedia.org/wiki/Halting_problem
zapl

48
if (isPrime(1234234234332232323423)){callSomething();}bu kod hiç bir şey çağırıp çağırmayacak mı? Bir işlevin çağrılıp çağrılmadığına karar vermenin, programa dahil etmekten çok daha pahalı olduğu başka birçok örnek vardır.
idclev 463035818

33
public static void main(String[] args) {int counterexample = findCollatzConjectureCounterexample(); System.out.println(counterexample);}println çağrı ölü kodu mu? İnsanlar bile bunu çözemez!
user253751

15
@ tobi303 harika bir örnek değil, asal sayıları çarpanlarına ayırmak gerçekten çok kolay ... görece verimli bir şekilde çarpanlarına ayırmak değil. Durdurma problemi çözülemez olan NP'de değildir.
en_Knight

57
@alephzero ve en_Knight - İkiniz de yanılıyorsunuz. isPrime harika bir örnektir. İşlevin bir Başbakan Numarası kontrol ettiğini varsaydınız. Belki bu numara bir seri numaraydı ve kullanıcının Amazon Prime üyesi olup olmadığını görmek için bir veritabanı araması yapıyor mu? Bunun harika bir örnek olmasının nedeni, koşulun sabit olup olmadığını bilmenin tek yolunun isPrime işlevini gerçekten yürütmektir. Şimdi bu Derleyicinin bir tercüman olmasını gerektirecektir. Ancak bu, hala verilerin değişken olduğu durumları çözmeyecektir.
Dunk

Yanıtlar:


275

Ölü kod sorunu Durma sorunuyla ilgilidir .

Alan Turing, bir program verilecek genel bir algoritma yazmanın ve o programın tüm girdiler için durup durmadığına karar vermenin imkansız olduğunu kanıtladı. Belirli program türleri için böyle bir algoritma yazabilirsiniz, ancak tüm programlar için yazamazsınız.

Bunun ölü kodla ilişkisi nedir?

Durdurma problemi ölü kod bulma problemine indirgenebilir . Yani ölü kodunu tespit edebilen bir algoritma bulursan olduğu herhangi bir program, o zaman ister teste o algoritmayı kullanarak herhangi bir program durduracak. Bunun imkansız olduğu kanıtlandığı için, ölü kod için bir algoritma yazmanın da imkansız olduğu anlaşılmaktadır.

Ölü kod için bir algoritmayı Durdurma sorunu için bir algoritmaya nasıl aktarırsınız?

Basit: Durdurmak için kontrol etmek istediğiniz programın sonuna bir satır kod eklersiniz. Ölü kod dedektörünüz bu hattın öldüğünü algılarsa, programın durmadığını bilirsiniz. Değilse, programınızın durduğunu bilirsiniz (son satıra ve ardından eklediğiniz kod satırına ulaşır).


Derleyiciler genellikle derleme zamanında kanıtlanabilecek şeyleri kontrol eder. Örneğin, derleme zamanında yanlış olduğu tespit edilebilen koşullara bağımlı bloklar. Veya return(aynı kapsam dahilinde) sonrasındaki herhangi bir ifade .

Bunlar özel durumlar ve bu nedenle onlar için bir algoritma yazmak mümkündür. Daha karmaşık vakalar için algoritmalar yazmak mümkün olabilir (bir koşulun sözdizimsel olarak bir çelişki olup olmadığını kontrol eden ve bu nedenle her zaman yanlış döndürülecek bir algoritma gibi), ancak yine de olası tüm durumları kapsamaz.


8
Burada durma sorununun uygulanamayacağını savunuyorum, çünkü gerçek dünyadaki her derleyicinin derleme hedefi olan her platform erişebileceği maksimum veri değerine sahip olduğundan, maksimum sayıda duruma sahip olacağı anlamına gelir. aslında bir sonlu durum makinesi, bir turing makinesi değil. Durdurma problemi FSM'ler için çözülemez, bu yüzden gerçek dünyadaki herhangi bir derleyici ölü kod tespiti yapabilir.
Vality

50
@Vality 64 bit işlemcileri 2 ^ 64 bayta hitap edebilir. 256 ^ (2 ^ 64) eyalette arama yaparken eğlenin!
Daniel Wagner

82
@DanielWagner Bu bir sorun olmamalı. Arama 256^(2^64)durumları ise O(1)ölü kod algılama polinom zamanlı olarak yapılabilir, böylece.
aebabis

13
@Leliel, bu alaycı bir şeydi.
Paul Draper

44
@Vality: Modern bilgisayarların çoğunda diskler, giriş aygıtları, ağ iletişimi vb. Bulunur. Herhangi bir tam analiz, kelimenin tam anlamıyla internet ve ona bağlı her şey dahil olmak üzere tüm bu cihazları dikkate almalıdır. Bu izlenebilir bir sorun değil.
Nat

77

Durma probleminin kararsızlığının klasik kanıtını alalım ve durma dedektörünü bir ölü kod detektörüne değiştirelim!

C # programı

using System;
using YourVendor.Compiler;

class Program
{
    static void Main(string[] args)
    {
        string quine_text = @"using System;
using YourVendor.Compiler;

class Program
{{
    static void Main(string[] args)
    {{
        string quine_text = @{0}{1}{0};
        quine_text = string.Format(quine_text, (char)34, quine_text);

        if (YourVendor.Compiler.HasDeadCode(quine_text))
        {{
            System.Console.WriteLine({0}Dead code!{0});
        }}
    }}
}}";
        quine_text = string.Format(quine_text, (char)34, quine_text);

        if (YourVendor.Compiler.HasDeadCode(quine_text))
        {
            System.Console.WriteLine("Dead code!");
        }
    }
}

Eğer YourVendor.Compiler.HasDeadCode(quine_text)getiri false, daha sonra hat System.Console.WriteLn("Dead code!");bu program aslında çok hiç yürütülmez gelmez ölü kodu var ve dedektör yanlıştı.

Ancak geri dönerse true, satır System.Console.WriteLn("Dead code!");yürütülür ve programda daha fazla kod olmadığından, hiç ölü kod yoktur, bu yüzden tekrar dedektör yanlıştı.

İşte orada, sadece "Ölü kod var" veya "Ölü kod yok" döndüren bir ölü kod dedektörü bazen yanlış cevaplar vermelidir.


1
Eğer argümanınızı doğru anladıysam, teknik olarak başka bir seçenek, ölü kod dedektörü olan bir yazı yazmak mümkün değildir, ancak genel durumda bir ölü kod dedektörü yazmak mümkündür. :-)
abligh

1
Godelian cevabı için artış.
Jared Smith

@abligh Ugh, bu kötü bir kelime seçimiydi. Aslında kendisine ölü kod dedektörünün kaynak kodunu değil, onu kullanan programın kaynak kodunu besliyorum. Elbette, bir noktada muhtemelen kendi koduna bakmak zorunda kalacaktı, ama bu onun işi.
Joker_vD

65

Durma problemi çok belirsiz ise, bu şekilde düşünün.

Tüm pozitif tamsayıların n için doğru olduğuna inanılan , ancak her n için doğru olduğu kanıtlanmayan bir matematik problemi alın . Buna iyi bir örnek, Goldbach'ın ikiden büyük herhangi bir pozitif tamsayının iki asalın toplamı ile temsil edilebileceği iddiasıdır. Sonra (uygun bir bigint kütüphanesi ile) bu programı çalıştırın (pseudocode aşağıdaki gibidir):

 for (BigInt n = 4; ; n+=2) {
     if (!isGoldbachsConjectureTrueFor(n)) {
         print("Conjecture is false for at least one value of n\n");
         exit(0);
     }
 }

Uygulanması isGoldbachsConjectureTrueFor(), okuyucu için bir alıştırma olarak bırakılmıştır, ancak bu amaçla,n

Şimdi, mantıksal olarak yukarıdakilerin ikisine de eşit olması gerekir:

 for (; ;) {
 }

(yani sonsuz bir döngü) veya

print("Conjecture is false for at least one value of n\n");

çünkü Goldbach'ın varsayımı ya doğru ya da doğru olmamalıdır. Bir derleyici her zaman ölü kodu ortadan kaldırabilseydi, her iki durumda da ortadan kaldırmak için kesinlikle ölü kod olurdu. Ancak bunu yaparken en azından derleyicinizin keyfi olarak zor sorunları çözmesi gerekir. Biz sorunları sağlayabilir kanıtlanabilir sert kodun biraz ortadan kaldırmak için hangi belirlemek için (örneğin NP-tam problemleri) çözmek zorunda kalacağını. Örneğin bu programı alırsak:

 String target = "f3c5ac5a63d50099f3b5147cabbbd81e89211513a92e3dcd2565d8c7d302ba9c";
 for (BigInt n = 0; n < 2**2048; n++) {
     String s = n.toString();
     if (sha256(s).equals(target)) {
         print("Found SHA value\n");
         exit(0);
     }
 }
 print("Not found SHA value\n");

programın "Bulunan SHA değeri" veya "Bulunmayan SHA değeri" (hangisinin doğru olduğunu söyleyebilirseniz bonus puanları) yazdıracağını biliyoruz. Ancak, bir derleyicinin 2 ^ 2048 yineleme sırasını alacak şekilde makul bir şekilde optimize edebilmesi için. Aslında, yukarıdaki programın herhangi bir optimizasyon olmadan herhangi bir şey basmak yerine evrenin ısı ölümüne kadar çalışacağını (ya da çalışabileceğini) tahmin ettiğim için büyük bir optimizasyon olurdu.


4
Bugüne kadar verilen en iyi cevap +1
jean

2
İşleri özellikle ilginç kılan şey, C Standardının döngülerin sona ereceğini varsaymak söz konusu olduğunda izin verdiği veya izin vermediği konusundaki belirsizliktir. Bir derleyicinin, sonuçlarının gerçekten gerekli olacağı noktaya kadar sonuçları kullanılabilecek veya kullanılamayacak yavaş hesaplamaları ertelemesine izin vermenin değeri vardır; bu optimizasyon bazı durumlarda derleyici hesaplamaların sonlandığını kanıtlayamasa bile yararlı olabilir.
supercat

2
2 ^ 2048 yineleme? Derin Düşünce bile vazgeçerdi.
Peter Mortensen

Bu hedef 64 onaltılık basamaklı rastgele bir dize olsa bile, çok yüksek olasılıkla "Bulunan SHA değeri" yazdıracaktır. Sürece sha256getiri bir bayt dizisi ve bayt dizileri kendi dilinizde dizeleri eşit kıyaslanamaz.
user253751

4
Implementation of isGoldbachsConjectureTrueFor() is left as an exercise for the readerBu beni kıkırdadı.
biziclop

34

C ++ veya Java'nın bir Evaltür işlevi olup olmadığını bilmiyorum , ancak birçok dil adıyla çağrı yöntemlerini yapmanıza izin veriyor . Aşağıdaki (kabul edilmiş) VBA örneğini düşünün.

Dim methodName As String

If foo Then
    methodName = "Bar"
Else
    methodName = "Qux"
End If

Application.Run(methodName)

Çağrılacak yöntemin adını çalışma zamanına kadar bilmek mümkün değildir. Bu nedenle, tanım olarak, derleyici, belirli bir yöntemin asla çağrılmadığını kesin olarak kesin olarak bilemez.

Aslında, bir yöntemi isimle çağırmak örneği verildiğinde, dallanma mantığı bile gerekli değildir. Basitçe söylemek gerekirse

Application.Run("Bar")

Derleyicinin belirleyebileceğinden daha fazla. Kod derlendiğinde, tüm derleyici bu yönteme belirli bir dize değerinin iletildiğini bilir. Bu yöntemin çalışma zamanına kadar var olup olmadığını kontrol etmez. Yöntem başka bir yerde çağrılmazsa, daha normal yöntemlerle, ölü yöntemleri bulma girişimi yanlış pozitifler döndürebilir. Aynı sorun, kodun yansıma yoluyla çağrılmasını sağlayan herhangi bir dilde de mevcuttur.


2
Java (veya C #) 'da bu yansıma ile yapılabilir. C ++ muhtemelen bunu yapmak için makro kullanarak bazı nastiness çekebilir. Güzel olmaz, ancak C ++ nadiren olur.
Darrel Hoffman

6
@DarrelHoffman - Kodlar derleyiciye verilmeden önce makrolar genişletilir, bu nedenle makrolar bunu nasıl yapacağınız kesinlikle değildir. İşlevlere işaret etmek, bunu nasıl yapacağınızdır. Yıllar içinde C ++ kullanmadım, bu yüzden tam tip isimlerim yanlışsa beni affedin, ancak işlev işaretleyicilerine bir dizeler haritası saklayabilirsiniz. Ardından, kullanıcı girişinden bir dizeyi kabul eden, haritadaki dizeyi arar ve ardından işaret edilen işlevi yürütür.
ArtOfWarfare

1
@ArtOfWarfare nasıl yapılabileceğinden bahsetmiyoruz. Açıkçası, bu durumu bulmak için kodun anlamsal analizi yapılabilir, mesele derleyicinin yapmamasıydı . Belki de olabilir, ama değil.
RubberDuck

3
@ArtOfWarfare: Nitpick yapmak istiyorsanız, kesinlikle. Ön işlemcinin derleyicinin bir parçası olduğunu düşünüyorum, ancak teknik olarak olmadığını biliyorum. Her neyse, işlev işaretçileri, işlevlerin herhangi bir yere doğrudan başvurulmadığı kuralını kırabilir - bunlar, doğrudan çağrı yerine bir işaretçi gibi, C #'daki bir temsilci gibi. C ++ bir derleyicinin tahmin etmesi çok daha zordur, çünkü dolaylı olarak işleri yapmanın birçok yolu vardır. "Tüm referansları bul" kadar basit görevler bile, typedefs, makrolar, vb. Gizlemek gibi önemsiz değildir. Hiç şüphe yok ki ölü kodu kolayca bulamıyor.
Darrel Hoffman

1
Bu sorunla yüzleşmek için dinamik yöntem çağrılarına bile ihtiyacınız yoktur. Herhangi bir genel yöntem, Java veya C # 'da zaten derlenmiş sınıfa veya dinamik bağlantı mekanizmasına sahip başka bir derlenmiş dile bağlı olacak henüz yazılmamış bir işlevle çağrılabilir. Derleyiciler bunları "ölü kod" olarak ortadan kaldırırsa, önceden derlenmiş kütüphaneleri dağıtım için paketleyemezdik (NuGet, kavanozlar, ikili bileşenli Python tekerlekleri).
jpmc26

12

Koşulsuz ölü kod gelişmiş derleyiciler tarafından algılanabilir ve kaldırılabilir.

Ancak şartlı ölü kod da vardır. Bu, derleme sırasında bilinemeyen ve yalnızca çalışma zamanı sırasında algılanabilen koddur. Örneğin, bir yazılım, kullanıcı tercihine bağlı olarak belirli özellikleri içerecek veya hariç tutacak şekilde yapılandırılabilir ve kodun belirli bölümlerinin belirli senaryolarda ölü gibi görünmesini sağlar. Bu gerçek ölü kod değil.

Verimlilik için test yapabilen, bağımlılıkları çözebilen, koşullu ölü kodu kaldırabilen ve yararlı kodu çalışma zamanında yeniden birleştirebilen özel araçlar vardır. Buna dinamik ölü kod eliminasyonu denir. Ama gördüğünüz gibi derleyicilerin kapsamı dışında.


5
"Koşulsuz ölü kod gelişmiş derleyiciler tarafından algılanabilir ve kaldırılabilir." Bu muhtemel görünmüyor. Kod ölümü, verilen bir işlevin sonucuna bağlı olabilir ve verilen işlev, keyfi sorunları çözebilir. Bu nedenle ifadeniz, gelişmiş derleyicilerin keyfi sorunları çözebileceğini ileri sürüyor.
Taemyr

6
@Taemyr O zaman koşulsuz ölü olduğu bilinmezdi, şimdi olur mu?
JAB

1
@Taemyr "Koşulsuz" kelimesini yanlış anlamış gibisiniz. Kod ölümü bir işlevin sonucuna bağlıysa, koşullu ölü koddur. "Koşul" fonksiyonun sonucudur. "Koşulsuz" olmak için herhangi bir sonuca bağlı olmamalıdır .
Kyeotic

12

Basit bir örnek:

int readValueFromPort(const unsigned int portNum);

int x = readValueFromPort(0x100); // just an example, nothing meaningful
if (x < 2)
{
    std::cout << "Hey! X < 2" << std::endl;
}
else
{
    std::cout << "X is too big!" << std::endl;
}

Şimdi 0x100 bağlantı noktasının yalnızca 0 veya 1 döndürecek şekilde tasarlandığını varsayın. Bu durumda derleyici elsebloğun hiçbir zaman yürütülmeyeceğini anlayamaz .

Ancak bu temel örnekte:

bool boolVal = /*anything boolean*/;

if (boolVal)
{
  // Do A
}
else if (!boolVal)
{
  // Do B
}
else
{
  // Do C
}

Burada derleyici elsebloğun ölü bir kod olduğunu hesaplayabilir . Böylece derleyici ölü kod hakkında ancak ölü kodu anlamaya yetecek kadar veri varsa ve verilen bloğun ölü kod olup olmadığını anlamak için bu verilerin nasıl uygulanacağını bilmelidir.

DÜZENLE

Bazen veriler derleme zamanında kullanılamaz:

// File a.cpp
bool boolMethod();

bool boolVal = boolMethod();

if (boolVal)
{
  // Do A
}
else
{
  // Do B
}

//............
// File b.cpp
bool boolMethod()
{
    return true;
}

A.cpp derlenirken derleyici boolMethodher zaman geri döndüğünü bilemez true.


1
Derleyicinin bilmediği kesin olarak doğru olsa da, bağlayıcının bilip bilemeyeceğini sormak sorunun ruhu içinde olduğunu düşünüyorum .
Casey Kuball

1
@Darthfett Bağlayıcının sorumluluğu yoktur. Linker derlenen kodun içeriğini analiz etmez. Bağlayıcı (genel olarak konuşursak) sadece yöntemleri ve küresel verileri birbirine bağlar, içeriği umursamaz. Ancak bazı derleyiciler kaynak dosyalarını (ICC gibi) birleştirme ve ardından optimizasyonu gerçekleştirme seçeneğine sahiptir. Bu durumda DÜZENLEME kapsamındaki durum kapsanır, ancak bu seçenek özellikle proje büyük olduğunda derleme süresini etkiler.
Alex Lop.

Bu cevap benim için yanıltıcı görünüyor; tüm bilgilerin mevcut olmadığı için mümkün olmadığı iki örnek veriyorsunuz, ancak bilgi mevcut olsa bile bunun imkansız olduğunu söylememeli misiniz?
Anton Golov

@AntonGolovO her zaman doğru değildir. Çoğu durumda bilgi orada olduğunda, derleyiciler ölü kodu tespit edebilir ve optimize edebilir.
Alex Lop.

@abforce sadece bir kod bloğu. Başka bir şey olabilirdi. :)
Alex Lop.

4

Derleyici her zaman bazı bağlam bilgilerine sahip olmayacaktır. Örneğin, bir çift değerin asla 2'yi aşmadığını biliyorsunuz, çünkü bu matematiksel işlevin bir özelliği, bir kütüphaneden kullanıyorsunuz. Derleyici kodu kütüphanede bile görmez ve tüm matematiksel işlevlerin tüm özelliklerini asla bilemez ve bunları uygulamak için tüm garip ve karmaşık yolları tespit edemez.


4

Derleyici tüm programı mutlaka görmez. Paylaşılan kitaplığı çağıran bir programım olabilir, bu da programımda doğrudan çağrılmayan bir işleve geri döner.

Dolayısıyla, derlendiği kitaplıkla ilgili ölü bir işlev, çalışma zamanında bu kitaplığın değiştirilmesi durumunda canlanabilir.


3

Bir derleyici tüm ölü kodları doğru bir şekilde ortadan kaldırabilirse, buna tercüman denir .

Bu basit senaryoyu düşünün:

if (my_func()) {
  am_i_dead();
}

my_func() rastgele kod içerebilir ve derleyicinin doğru veya yanlış döndürüp döndürmediğini belirlemesi için kodu çalıştırması veya kodu çalıştırmaya işlevsel olarak eşdeğer bir şey yapması gerekir.

Bir derleyici fikri, kodun sadece kısmi bir analizini gerçekleştirerek ayrı bir çalışma ortamının işini basitleştirmesidir. Tam bir analiz yaparsanız, bu artık bir derleyici değildir.


Derleyiciyi bir işlev c(), nerede c(source)=compiled codeve çalışma ortamını r(), nerede olarak r(compiled code)=program outputgörürseniz, değerini hesaplamanız gereken herhangi bir kaynak kodunun çıktısını belirlemek için r(c(source code)). Hesaplama Eğer c()değerinin bilinmesini gerektirir r(c())herhangi bir giriş için ayrı bir gerek yoktur r()ve c(): Eğer bir işlev türetmek sadece olabilir i()dan c()öyle ki i(source)=program output.


2

Diğerleri durma problemi ve benzerleri hakkında yorum yaptı. Bunlar genellikle fonksiyon kısımları için geçerlidir. Ancak, tüm bir türün (sınıf / vb.) Bile kullanılıp kullanılmadığını bilmek zor / imkansız olabilir.

.NET / Java / JavaScript ve diğer çalışma zamanı güdümlü ortamlarda yansıma yoluyla yüklenecek durdurma türleri yoktur. Bu, bağımlılık enjeksiyon çerçeveleri ile popülerdir ve serileştirme veya dinamik modül yükleme karşısında akıl yürütmek daha da zordur.

Derleyici bu tür türlerin yüklenip yüklenmeyeceğini bilemez. İsimleri olabilir zamanında harici yapılandırma dosyalarından gelir.

Kullanılmayan kod alt bölümlerini güvenli bir şekilde kaldırmaya çalışan araçlar için yaygın bir terim olan ağaç sallayarak aramak isteyebilirsiniz .


Java ve javascript hakkında bilmiyorum, ancak .NET aslında DI algılama (Agent Mulder denir) bu tür bir yeniden paylaşım eklentisi vardır. Tabii ki, yapılandırma dosyalarını algılayamayacak, ancak koddaki (çok daha popüler olan) confit'i algılayabiliyor.
Kravatlar

2

Bir işlev al

void DoSomeAction(int actnumber) 
{
    switch(actnumber) 
    {
        case 1: Action1(); break;
        case 2: Action2(); break;
        case 3: Action3(); break;
    }
}

Bunu kanıtlamak Can actnumberasla 2böylece Action2()asla denir ...?


7
İşlevin arayanlarını analiz edebiliyorsanız, bunu yapabilirsiniz, evet.
abligh

2
@abligh Ancak derleyici genellikle tüm çağrı kodlarını analiz edemez. Her neyse, mümkün olsa bile, tam analiz, gerekli tüm kontrol akışlarının sadece bir simülasyonunu gerektirebilir, bu da gerekli kaynaklar ve zaman nedeniyle neredeyse her zaman imkansızdır. Yani teorik olarak var olsa bile var 'bir kanıt Action2()denilen asla' uygulamada iddiasını kanıtlamak mümkün değildir - tam bir derleyici tarafından çözülemez . Aradaki fark 'X sayısı var' ile 'X sayısını ondalık olarak yazabiliriz' gibidir. Bazı X'ler için, ikincisi gerçek olmasına rağmen asla gerçekleşmeyecektir.
CiaPan

Bu kötü bir cevap. diğer cevaplar ise bilmenin imkansız olduğunu kanıtlıyoractnumber==2 . Bu cevap, karmaşıklığı bile belirtmeden zor olduğunu iddia ediyor.
MSalters

1

Durma sorununa katılmıyorum. Gerçekte asla ulaşılamayacak olmasına rağmen böyle bir kodu ölü demezdim.

Bunun yerine şunu düşünelim:

for (int N = 3;;N++)
  for (int A = 2; A < int.MaxValue; A++)
    for (int B = 2; B < int.MaxValue; B++)
    {
      int Square = Math.Pow(A, N) + Math.Pow(B, N);
      float Test = Math.Sqrt(Square);
      if (Test == Math.Trunc(Test))
        FermatWasWrong();
    }

private void FermatWasWrong()
{
  Press.Announce("Fermat was wrong!");
  Nobel.Claim();
}

(Tür ve taşma hatalarını dikkate almayın) Ölü kod?


2
Fermat'ın son teoremi 1994 yılında kanıtlanmıştır. Bu nedenle, yönteminizin doğru bir şekilde uygulanması FermatWasWrong'u asla çalıştırmaz. Uygulamanızın FermatWasWrong'u çalıştıracağından şüpheleniyorum, çünkü şamandıraların hassasiyet sınırına vurabilirsiniz.
Taemyr

@Taemyr Aha! Bu program Fermat'ın Son Teoremini doğru bir şekilde test etmez; test ettiği şey için bir karşı örnek N = 3, A = 65536, B = 65536 (Test = 0 veren)
user253751

@immibis Evet, şamandıraların hassasiyeti sorun haline gelmeden önce int taşması gerektiğini özledim.
Taemyr

@ immibis Yazımın altına dikkat edin: Tür ve taşma hatalarını dikkate almayın. Sadece kararın temeli olarak çözülmemiş bir sorun olduğunu düşündüğüm şeyi alıyordum - kodun mükemmel olmadığını biliyorum. Zaten kaba-kaba zorlanamayan bir problem.
Loren Pechtel

-1

Şu örneğe bakın:

public boolean isEven(int i){

    if(i % 2 == 0)
        return true;
    if(i % 2 == 1)
        return false;
    return false;
}

Derleyici bir int'in çift veya tek olabileceğini bilemez. Bu nedenle derleyici kodunuzun anlamını anlayabilmelidir. Bu nasıl uygulanmalı? Derleyici, en düşük getirinin asla yürütülmeyeceğinden emin olamaz. Bu nedenle derleyici ölü kodu algılayamaz.


1
Gerçekten mi? Bunu C # + ReSharper ile yazarsam birkaç ipucu alırım. Onları takip etmek sonunda bana kod veriyor return i%2==0;.
Thomas Weller

10
Örneğiniz ikna edici olmayacak kadar basit. Özgül durum i % 2 == 0ve i % 2 != 0hatta bir tamsayı değeri hakkında akıl yürütme gerektirmez (hala kolay yapmaktır) bir sabiti modulo, sadece alt ifade eleme ve genel prensibi (standartlaştırma, hatta) gerektirir if (cond) foo; if (!cond) bar;basitleştiirlebilir if (cond) foo; else bar;. Tabii ki "anlambilimi anlamak" çok zor bir sorundur, ancak bu yazı ne olduğunu göstermez ne de bu zor sorunun çözülmesinin ölü kod tespiti için gerekli olduğunu göstermez.

5
Örneğin, optimize edici bir derleyici ortak alt ifadeyi tespit edecek i % 2ve geçici bir değişkene çekecektir. Daha sonra, iki ififadenin birbirini dışladığını ve şu şekilde yazılabileceğini tanıyacaktır if(a==0)...else...ve sonra tüm olası yürütme yollarının ilk iki returnifadeden geçtiğini ve dolayısıyla üçüncü returnifadenin ölü kod olduğunu tespit edecektir . ( İyi bir optimize edici derleyici daha da agresiftir: GCC test kodumu bir çift bit manipülasyon işlemine dönüştürdü).
Mark

1
Bu örnek benim için iyi. Bir derleyicinin bazı gerçek durumlar hakkında bilgi sahibi olmadığı durumu temsil eder. Aynı şey geçerli if (availableMemory()<0) then {dead code}.
Küçük Santi

1
@LittleSanti: Aslında GCC, yazdığınız her şeyin ölü kod olduğunu tespit edecek ! Sadece {dead code}kısım değil . GCC bunu kaçınılmaz olarak imzalı bir tamsayı taşması olduğunu kanıtlayarak keşfeder. Bu nedenle, yürütme grafiğinde bu yay üzerindeki tüm kodlar ölü koddur. GCC, bu yaya yol açan koşullu dalı bile kaldırabilir.
MSalters
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.