2010-06-21 5 views
8
const int bob = 0; 

if(bob) 
{ 
    int fred = 6/bob; 
} 

dostaniesz błąd na linii, gdzie podział odbywa się: „error C2124: Podziel MOD przez zero”MSVC++ błąd w dzieleniu przez 0, który nigdy się nie wydarzy! naprawić?

który jest kulawy, bo to jest tak samo nieuniknione, że „jeżeli” check nie powiedzie się, ponieważ jest to podział, który spowoduje, że div o 0. całkiem szczerze nie widzę powodu, dla którego kompilator mógłby ocenić cokolwiek w "if", z wyjątkiem zapewnienia integralności klamrowej.

tak, oczywiście, że przykład nie jest mój problem, mój problem jest, gdy robi skomplikowany szablon rzeczy, aby spróbować i zrobić jak najwięcej w czasie kompilacji, jak to możliwe, w niektórych przypadkach argumenty mogą być 0.

jest tam mimo naprawić ten błąd? lub wyłączyć? lub jakikolwiek lepszy sposób obejścia tego problemu:

Obecnie jedyną pracą, jaką mogę wymyślić (co zrobiłem wcześniej, gdy napotkałem ten sam problem z dostępem rekursywnym enumem) jest użycie specjalizacji szablonów do zrobienia "jeśli".

O tak, używam programu Visual Studio Professional 2005 SP1 z poprawką vista/win7.

+0

Możesz spróbować przypisać do zmiennej lokalnej, a następnie ją podzielić. – Artelius

+2

Dunno, jeśli to zadziała, ale co powiesz na: int fred = 6/(bob? Bob: 1); –

+0

@Jeremy Friesner: miło! to działa, i rozwiąże mój problem, proszę, ułóż to jako odpowiedź! – matt

Odpowiedz

4

Przypuszczam kompilator stara się optymalizować fragment kodu od bob definiuje const, tak że wartość początkowa fred może być ustalona w czasie kompilacji. Być może możesz zapobiec tej optymalizacji, deklarując bob non-const lub używając słowa kluczowego volatile.

+0

masz rację, problem polega na tym, że kompilator wewnętrznie wykonuje matematykę i atakuje, gdy próbuje podzielić przez zero. niestety cały sens tego, co próbuję zrobić, to skłonić kompilator do wykonania matematyki w czasie kompilacji :(w przeciwnym razie sugerowane jest rozwiązanie błędu: – matt

+0

Nie - nie jest to optymalizacja. – MSalters

3

Czy możesz podać więcej szczegółów na temat tego, co próbujesz zrobić z szablonami? Być może możesz użyć wyspecjalizowanego szablonu dla 0, który nie robi nic podobnego do starego dobrego przykładu Factorial i całkowicie pomija ten błąd.

template <int N> 
struct Blah 
{ 
    enum { value = 6/N }; 
}; 

template <> 
struct Blah<0> 
{ 
    enum { value = 0 }; 
}; 
+0

tak, to również naprawi mój problem i właśnie to miałem na myśli, gdy powiedziałem: "użyj specjalizacji szablonu, aby zrobić" jeśli "" jako obejście problemu: – matt

+0

Niestety tego nie zauważyłem :), ale jest preferowany sposób uniknięcia tych problemów, a także pozwala kompilatorowi więcej pracy w czasie kompilacji. – Gary

+0

tak, jest to również jedyny znany mi sposób naprawiania innych takich błędów, na przykład wywołań rekursywnych, na przykład: CRASH będzie kompilatorem, ponieważ zawsze będzie wyświetlał obie strony "if", zawiedzie lub nie: enum {value = (N> 10)? 1337: Blah :: wartość}; – matt

3

Problem - i kompilator wyboru w tym - jest bob jest integralnej stałej ekspresji, jak to 6. Dlatego 6/Bob również ICE i musi ocenić w czasie kompilacji .

Istnieje bardzo proste rozwiązanie: inline int FredFromBob(int bob) { return 6/bob; } - Wyrażenie wywołania funkcji nigdy nie jest ICE, nawet jeśli funkcja jest banalna i zadeklarowana jako wbudowana.

+0

Tak, stała może być używana jako parametr szablonu. Kompilator nie może po prostu pominąć tworzenia szablonów, nawet gdyby wystąpiły one w części kodu, który jest nieosiągalny w środowisku wykonawczym. – MSalters

Powiązane problemy