2013-01-11 5 views
6

Podczas wykonywania programowania używam sprawdzania poprawności a także NULL.Używanie sprawdzania poprawności wskaźnika Assert i NULL, co jest lepsze w użyciu

Ale jak wiem assert będzie przydatny tylko w trybie DEBUG.

Moje pytanie jest Załóżmy, że mam wewnętrzny wskaźnik której jestem pewien mogę być NULL przykładową funkcję powracającego wskaźnik (ale wskaźnik nie jest członkiem klasy) w takich przypadkach można używać dochodzić

test* ptr = fun(); // return a pointer of type test 
assert(ptr); 

//do some operation 

lub NULL wskaźnik walidacji

test* ptr = fun(); // return a pointer of type test 
assert(ptr); 
if (NULL != ptr) 
{ 
    //do some operation 
} 

Tutaj której praktyka kod jest good.As na moje zaniżenie to będzie drugi. Ponieważ napotkałem w niektórych sytuacjach, gdy wartość ptr zwraca NULL ze względu na niektóre nieprawidłowe przypadki, o których nawet nie myślimy.

Ale czy mamy jakieś inne lepsze opcje?

+0

Dlaczego to pytanie jest głosowane na zakończenie? To jest poprawne pytanie. – Nawaz

+0

Czy rozważałeś, aby nie zwracać wartości null? Znacznie łatwiej byłoby napisać kod. To znaczy. puste tablice/specjalne [obiekty puste] (http://en.wikipedia.org/wiki/Null_Object_pattern) i wyjątki mogą znacznie ograniczać potrzebę zwracania wartości zerowej, a zatem sprawdzania jej. –

+0

@AlexeiLevenkov sprawdź drugi przypadek –

Odpowiedz

3

Rzeczywiste rozwiązanie zależy od semantycznego funkcji fun.

Jeśli powrocie NULL jest niepoprawne semantycznie, to myślę fun powinny rzucać odpowiedniego wyjątku (takie jak std::logic_error) zamiast powrocie NULL, i można użyć assert w miejscu połączenia, aby fun działa poprawnie, a jeśli to nie działa poprawnie, przerwij program. W ten sposób błąd w fun nie propaguje się do reszty programu, ponieważ jest on od razu pobierany.

Jednak jeśli powrocie NULL z fun jest semantycznie poprawny, to należy sprawdzić wartość zwracaną na wezwanie miejscu używając if i assert nie jest naprawdę potrzebne w tym przypadku, ponieważ będzie używany if tak.

1. Można również użyć std::runtime_error lub .

+0

niektóre nieprawidłowe scenariusze mogą przywrócić wartość o ** fun ** jako NULL lub uszkodzenie pamięci dla tej zmiennej.Tak też inne wątki. Co w końcu oznacza, że ​​zmuszam mnie do użycia drugiego przypadku ... –

0

Tak jak wspomniałeś, assert jest tylko podczas debugowania, pomagając programistom zidentyfikować, gdzie poszło nie tak. Nie ma żadnej wartości w produkcji i dlatego wolę używać drugiej metody, jeśli masz jakiekolwiek wątpliwości, że wskaźnik może mieć wartość NULL.

+0

Tak, wolę drugą metodę .... ale zabawa() jest idealnie nie może zwrócić NULL. Nie jest to więc dodatkowa kontrola warunku lub zawsze gra bezpieczniej z bezpieczną stroną :-) –

+1

Ale jeśli masz assert w debugowaniu, nigdy nie przetestujesz ścieżki kodu, gdzie wskaźnik jest pusty. Oznacza to, że jeśli zdarzy się to podczas produkcji, kolejne ścieżki kodu nigdy nie zostaną przetestowane, ponieważ wskaźnik jest pusty, a oryginalny błąd może zostać zamaskowany przez późniejsze wykonanie kodu. Późniejsza realizacja kodu może, ale nie musi, wyjść z błędu - ten fakt nigdy nie został przetestowany. –

+0

@CharlesBailey nie podejrzewam, że wartość wskaźnika ma wartość NULL kiedykolwiek. –

1

Polecam użyć własnego kodu do asercji. jak powiedziałeś, asercja działa tylko w trybie debugowania.

Tak więc, jeśli działa w trybie zwolnienia, nie działa.

jeśli używasz własnego kodu potwierdzenia. możesz po prostu dowiedzieć się, co jest nie tak.

test* ptr = fun(); // return a pointer of type test 
MyOwnAssert(ptr); 

void MyOwnAssert(void* pPointer) 
{ 
    if (NULL == pPointer) 
    abort(); 
}  
+0

w powyższym kodzie sprawdzasz, czy NULL nie jest potwierdzeniem i myślę, że powyższy kod można uprościć, używając MACRO zamiast funkcji –

+0

tak, oczywiście. ale tu nie o to chodzi. – VariOov

4

assert mówi: „jeśli to nie jest prawda, nie jest to błąd logiczny w moim kodu”. Jeśli wstawiasz kod, aby obsłużyć fakt, że wskaźnik może mieć wartość NULL, to wywołanie potwierdzenia jest zbędne. Zamiast tego należy dodać rejestrowanie i obsługę do przypadku "innego".W ten sposób twoja wersja debugowania będzie działać w taki sam sposób jak twoja wersja wydania, nawet w przypadku wskaźnika pustego wskaźnika.

Jeśli naprawdę masz na myśli twierdzenie i musisz przerwać na pustym wskaźniku, włącz w swoim wydaniu kompilacje lub użyj mechanizmu assert z włączoną wersją.

Jedynym powodem asertywacji tylko debugowania jest sprawdzenie błędu logicznego, który jest zbyt drogi w kodzie zwolnienia. Zwykle kontrola zerowa wskaźnika nie pasuje do tej kategorii.

0

To, co możesz zrobić z asersem, to twój wybór: możesz go użyć, jeśli chcesz.

Powiedziałbym, że używanie assert() jest lepsze, jeśli chcesz wcześnie wykryć błędy. Zwłaszcza, jeśli nie powinno się zdarzyć, że jest to wskaźnik NULL.
Można nawet umieścić tam kod Google Breakpad, więc za każdym razem, gdy naciśniesz wskaźnik NULL, w tym momencie wysyłany jest raport z pełnym stosem.

W przypadkach, w których wskaźnik NULL jest możliwy (i czasami oczekuje się ...), to myślę, że kontrola NULL jest lepsza. Ale powiedziałbym, że w tym momencie twój kod jest w jakiś sposób błędny, jeśli musi się zgadzać z przekazywaniem wskaźników NULL.

+0

możesz wyjaśnić wiele o ** Google Breakpad ** za pomocą małej próbki? –

+0

Czy nie http://code.google.com/p/google-breakpad/wiki/LinuxStarterGuide? – Gui13

Powiązane problemy