2010-08-20 17 views
11

Der folgende Testcode wird in VS entweder mit Debug oder Release und auch in GCC korrekt ausgeführt. Es funktioniert auch korrekt für ICC mit Debug, aber nicht wenn Optimierung aktiviert ist (-O2).Können Compiler Endlosschleifen entfernen wie Intel C++ Compiler mit -O2?

#include <cstdio> 

class tClassA{ 
public: 
    int m_first, m_last; 

    tClassA() : m_first(0), m_last(0) {} 
    ~tClassA() {} 

    bool isEmpty() const {return (m_first == m_last);} 
    void updateFirst() {m_first = m_first + 1;} 
    void updateLast() {m_last = m_last + 1;} 
    void doSomething() {printf("should not reach here\r\n");} 
}; 

int main() { 
    tClassA q; 
    while(true) { 
    while(q.isEmpty()) ; 
    q.doSomething(); 
    } 
    return 1; 
} 

Es soll bei while(q.isEmpty()) stoppen. Wenn -O2 unter ICC (release) aktiviert ist, beginnt es jedoch unendlich "zu tun".

Da es sich um Single-Threaded-Programm undisEmpty() sollte als true ausgewertet werden, ich keinen Grund, das ICC auf diese Weise finden sich verhalten sollten? Vermisse ich etwas?

+0

es, wenn m_first und m_last hilft als 'flüchtig' deklariert werden? Ich habe keinen Zugang zu ICC. – Chubsdad

+0

Noch ein wilder Gedanke: Hat es damit zu tun, dass% s nicht mit printf angegeben ist. printf ("% s", "sollte nicht hierher \ r \ n" kommen) ;? – Chubsdad

+5

Related: [Sind Compiler erlaubt, unendliche Schleifen zu beseitigen?] (Http://stackoverflow.com/questions/2178115/are-compilers-allowed-to-eliminate-infinite-loops) –

Antwort

0

Am besten nehmen Sie den resultierenden Binärschritt und teilen die Hauptfunktion auf und sehen, welche Baugruppe generiert wurde. Ich sage nicht, dass Sie einen Fehler sehen können, aber Sie können sehen, ob etwas optimiert wurde.

+0

Sie können nicht. Der Asm Code ist alles weg optimiert und man kann nichts sehen. – Samuel

+0

Ich bin mir nicht sicher, was das bedeutet. Willst du damit sagen, dass du die resultierende Binärdatei zerlegt hast und die while() Schleife weg war? – linuxuser27

2

Es klingt sicher wie ein Fehler. Hier ein ist (ziemlich wild) erraten, über welche Argumentation führen zu ihm haben könnte ...

Nach inlining, es sieht:

while (q.m_first == q.m_last) /* do nothing */ ; 
do_something(); 

und jede Folge von do nothing repeatedly ; do something kann übersetzt werden, um einfach „etwas tun“. Dieser fällt ab, wenn der wiederholte Teil endlos ist (wie in diesem Fall). Aber vielleicht testen sie ihre Zusammenstellung nicht an Beispielen, die absichtlich endlose Schleifen haben ;-).

+0

Das Erkennen von intentionalen Endlosschleifen ist im Grunde das Halteproblem, stattdessen nehmen sie an, dass es, da es keine sichtbaren Nebenwirkungen hat, nichts tut und daher für das Programm nutzlos ist und entfernt werden kann. Offensichtlich ist IS für uns ein sichtbarer SDE-Effekt, aber nicht für die abstrakte C/C++ - Maschine, die durch den Standard definiert ist. Wenn Sie die Schleife wollen, dann müssen Sie den Compiler sagen, dass es tatsächlich das Programm beeinflusst, indem Sie z. B. eine der gelesenen Variablen flüchtig machen. – Dan

-3

Ich denke, es könnte Ihre Version von gcc gewesen sein. Ich habe dein Prog unter 4.4.2 kompiliert und es hat genau so funktioniert, wie es sein sollte.

+2

Dies ist icc, nicht gcc –

1

Jede Möglichkeit, den tatsächlichen Code, den Sie erstellt und ausgeführt haben, fehlte das Semikolon nach while(q.isEmpty())? Das würde sicherlich dazu führen, dass die nächste Zeile unendlich heißt.

+0

+1 für die Erinnerung an etwas ähnliches – Chubsdad

+0

1. Es gibt Semikolon 2. das gleiche Ergebnis mit while (q.isEmpty()) {}, oder while (q.isEmpty()) {true;} – Samuel

+0

Wer auch immer: War ein Down-Vote wirklich notwendig? Ich habe eine Reihe von Fällen auf SO gesehen, wo der gepostete Code nicht der genaue Code war und wo das tatsächliche Problem ausgelassen oder in der Übersetzung behoben wurde. Ich wollte nur sicherstellen, dass dies nicht das Ergebnis eines einfachen, aber leicht zu übersehenden Fehlers ist. (Haben wir nicht alle irgendwann mal wegen eines Fehlers ein falsches Semikolon verschwendet?) – TheUndeadFish

10

Da die while (q.isEmpty()) ;-Schleife keine Anweisungen enthält, die jemals einen von außen sichtbaren Nebeneffekt verursachen können, wird die gesamte Schleife nicht mehr optimiert. Es ist der gleiche Grund, dass:

for (int i = 0; i < 10; i++) 
    ; 

aus der Existenz optimiert werden könnte, solange i war nicht volatile (Läden volatile Objekte Teil der „von außen sichtbar“ Effekte eines Programms sind).

In der C-Sprache ist es eigentlich ein herausragender Streitpunkt darüber, ob eine Endlosschleife auf diese Weise wegoptimiert werden darf (ich weiß nicht, wie die Situation in C++ aussieht). Soweit ich weiß, wurde in dieser Frage noch kein Konsens erzielt - intelligente und sachkundige Menschen haben beide Seiten vertreten.

+0

Das könnte der Grund sein. Der folgende Code funktioniert ordnungsgemäß: static int A = 0; while (q.isEmpty()) {A = A + 1;} Aber nicht das Folgende: statisch int A = 1; while (q.isEmpty()) {A;} – Samuel

+1

Interessant. Eine Endlosschleife, die nichts tut - eine nette Optimierungsmöglichkeit (und es ist verständlich, warum jemand anderer Meinung ist). – Suma

+0

Noch eine Sache: Wenn while (true) für while (q.isEmpty()) verwendet wird, funktioniert der Code korrekt. – Samuel

1

Als eine kleine Nebensache, diese Version von ICC macht was Sie wollen. Das heißt, es ruft nie doSomething().

[9:41am][[email protected] /tmp] icc --version 
icc (ICC) 11.0 20081105 
1

Die C++ Standard ermöglicht Schleifen ohne Nebenwirkungen entfernt werden, auch wenn sie enden nicht:

Es ist allgemein der Ansicht, dass es wichtig ist es, die Transformation potenziell zu ermöglichen nicht endende Schleifen (z. B. durch Verschmelzen von zwei Schleifen, die über dieselbe potentiell unendliche Menge oder durch Eliminieren einer seiteneffektfreien Schleife iterieren, auch wenn sonst nicht in der 0 gerechtfertigt sein kannFall, in dem die erste Schleife nie endet. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm

die Diskussion hier ansehen: http://blog.regehr.org/archives/161