2013-05-22 8 views
12

Próbuję usunąć błąd, w którym plik wykonywalny generuje powtarzalne wyniki (które chcę), gdy jest wykonywany bezpośrednio z programu Visual Studio, ale robi , a nie generuje powtarzalne wyjście po uruchomieniu z wiersza polecenia. Jest to aplikacja jednowątkowa, więc nie powinno być żadnych dziwnych zachowań w zakresie czasu.Różnice między uruchamianiem pliku wykonywalnego z debugerem Visual Studio a bez debugowania

Czy ktoś może wyliczyć możliwe różnice między tymi dwoma środowiskami?

Jestem pewien, że rzeczywisty plik wykonywalny jest taki sam - oba są wersjami kompilacji i działają z tym samym plikiem .exe.

Oto środowisk i rezultaty:

  1. uruchomić bezpośrednio z wiersza poleceń (cmd): wyjście jednorazowych
  2. Run z Visual Studio debugowania (F5): wyjście Powtarzalne
  3. Run z Visual Studio bez debugowania (Ctrl-F5): Nieodwracalne wyjście

Wiem, że katalog roboczy może być inny, ale ręcznie dostosowuję to, aby upewnić się, że w katalogu roboczym jest identyczny.

Na podstawie tych wyników wygląda na to, że uruchomienie "z debugowaniem" (nawet w wersji Release) w jakiś sposób rozwiązuje problem. Czy to wskazuje na prawdopodobnego sprawcę? Jakie są różnice między uruchamianiem pliku wykonywalnego z debugowaniem i bez?

ROZWIĄZANIE: Jak wskazano w zaakceptowanej odpowiedzi, problemem była stertka debugowania. Problem polegał na tym, że w głębi naszego kodu ktoś miał dostęp do części dużego układu, zanim zostały zainicjalizowane. Podzieliły pamięć z malloc i nie zainicjowały pamięci do 0. Stuła debugowania (przypuszczam) wypełniłaby tablicę pewną wartością powtarzalną, podczas gdy debugger nie był podłączony (tj. Gdy uruchomiono z linii poleceń lub z Ctrl-F5) wartości były bardziej losowe i czasami powodowały niewielkie odchylenia w zachowaniu programu. Niestety, regulacja była tak subtelna, że ​​prawie nieodczuwalna, a wspomniane pytanie zostało poprawnie zresetowane po pierwszej "ramce" przetwarzania, ale warunki początkowe były już nieco inne i uszkodzenia zostały już wykonane. Teoria chaosu w akcji! Dzięki za wskazówki.

Jedna świetna wskazówka dotycząca debugowania, która pomogła: napisać niestandardowy malloc, który natychmiast zapełnia pamięć całkowicie losowymi danymi. W ten sposób możesz upewnić się, że poprawnie go zainicjujesz przed użyciem, w przeciwnym razie twoje wyniki będą (miejmy nadzieję) szalone przy każdym uruchomieniu - nawet w trybie debugowania z stertą debugowania!

+1

Zależy od kodu. Być może wyzwalasz niezdefiniowane zachowanie, które pojawia się tylko na wyższych poziomach optymalizacji. –

+1

Ale teoretycznie nie jest jedyną różnicą, że debugger nie jest dołączony? Kompilacja jest identyczna - Release build za każdym razem. Stopień optymalizacji się nie zmienia. – aardvarkk

+0

Wiem, że mówisz, że dostosowujesz się do katalogu roboczego, ale wydaje się, że to prawdopodobny sprawca. Innym problemem, na który powinienem poszukać, są zainstalowane biblioteki. VS obsługuje zależności (a jeśli tworzysz i instalujesz poprzez ClickOnce, który obsługuje twoje zależności), ale uruchomienie bezpośrednio z wiersza poleceń może nie. –

Odpowiedz

15

Windows Heap behaves differently if process is started under the debugger. Aby wyłączyć to zachowanie (w celu znalezienia problemu podczas debugowania) dodaj _NO_DEBUG_HEAP = 1 do środowiska (jak w this question).

Alternatywnie można dołączyć do procesu w trakcie wykonywania programu. Sterty nie wejdą wtedy w tryb debugowania. Dodaj linię DebugBreak() gdzieś na początku wykonywania, uruchom za pomocą Ctrl + F5 i rozpocznij debugowanie, gdy zostaniesz o to poproszony.

+0

Wydaje się to świetną wskazówką - spróbuję, dzięki! – aardvarkk

+0

Świetny dodatek również tam. Wydaje mi się, że jest to bardzo prawdopodobny problem - pewna wartość wartownika, która jest powtarzalna, gdy dołączony jest debugger, ale w przeciwnym razie jest to tylko informacja o śmieciach (a więc nieodwracalne zachowanie!). – aardvarkk

+0

To wskazało mi właściwy kierunek. Będę edytować pytanie z kilkoma szczegółami. Dzięki! – aardvarkk

0

Cóż, trudno powiedzieć, nie wiedząc nieco więcej o swoim kodzie. Miałem jednak podobny problem z programem wykonującym wiele arytmetyki zmiennoprzecinkowej (numery podwójnej precyzji).

Kwestia pojawiłaby się, gdy miałem do czynienia z liczbami, które były nieco inne, ale numerycznie nieodróżnialne dla maszyny. Jeśli dwa zakłady różnią się o mniej niż numeric_limits<double>::epsilon(), są one traktowane jako takie same dla urządzenia. Stąd, wyrażenia typu:

if (num1==num2)... 

lub

if (num1<num2)... 
... 

może spowodować kolorowych efektów.

Te kolorowe efekty mogą się różnić po uruchomieniu w trybie debugowania lub zwolnienia. Powodem jest to, że biblioteki uruchomieniowe debug/release różnią się. Ponadto, i co najważniejsze, kompilacja odbywa się za pomocą różnych optymalizacji kodu. Różnica między wersją debugowania wiersza polecenia a wersją okna debugowania (F5) jest również wyjaśniona przez subtelne różnice optymalizacyjne.

Jeśli używasz VS, możesz rzucić okiem na efekt różnych opcji kompilacji i optymalizacji w sekcji C/C++ i Linker menu Properties. Aby uniknąć tego problemu, zaleca się korzystanie z urządzeń numeric_limits z biblioteki STL <limits>. Na przykład implementacja mniejszego operatora powinna wyglądać mniej więcej tak:

bool operator<(double num1, double num2) { 
    double difference=fabs(num1-num2); 
    if (difference>numeric_limits<double>::epsilon()) { 
     if (num1 < num2) return true; 
     return false; 
    } 
    return false; 
} 
Powiązane problemy