2013-05-13 13 views
8

muszę STAN:złapać wszystkie rodzaj twierdzenia

try 
{ 
//bug condition 
} 
catch() 
{ 
//Remove file 
} 

To znaczy utworzyć jeden bardzo poufny plik którego dane nie mogą być oglądane przez osoby trzecie, ale kiedy każdy błąd wystąpił w kodzie mój plik został usunięty ze względu Nie wiem dokładnie, gdzie pojawiły się błędy.

Więc chcę złapać ten błąd za pomocą try and catch i chcę usunąć ten plik. Jak mogę złapać wyjątek w C++?

To spowoduje usunięcie pliku, jeśli wystąpił błąd.

odczuwalna:

try 
{ 
    char TempArray[10]; 
    char c = TempArray[11]; 
} 
catch 
{ 
    cout<<"Array out of boundry"; 
    deleteFile("Confi.txt"); 
} 
+1

'catch (...)' zrobi to, co chcesz. – Rapptz

+2

Łapiesz wyjątki, nie asercje. A catch-all catch to "catch (...)". – juanchopanza

+3

Twój przykładowy błąd wywołuje niezdefiniowane zachowanie i prawdopodobnie nie spowoduje wyjątku i nie zostanie przechwycony. – interjay

Odpowiedz

8

słowo o bezpieczeństwie: Jeśli utworzysz plik na dysku twardym, informacje poufne, każdy może wyłączyć komputer, gdy proces jest uruchomiony i plik jest nadal otwarty, wyjmij dysk twardy i przeczytaj jego treść.

Jeśli plik znajduje się na serwerze, możesz zrobić to samo, wstrzymując proces przed usunięciem pliku.

Nawet jeśli usunięto plik z systemu plików, najprawdopodobniej nadal można go odczytać, ponieważ usunięcie pliku nie powoduje wyczyszczenia jego zawartości.

Zalecam, aby nie zajmować się poufnymi informacjami, dopóki nie uzyska się niezbędnej wiedzy specjalistycznej - a nie ucząc się z języka SO. Ale jeśli musisz to zrobić, myślę, że proces watchdog sugeruje tutaj + szyfrowanie jest drogą do zrobienia.

4

przede wszystkim:

Nie chcesz tego robić.

Wyjątki nie są przeznaczone do obsługi błędów, ale powodują błędy w czasie wykonywania, które uniemożliwiają spełnienie przez funkcję warunków innych funkcji, do których ma zadzwonić, lub dotrzymania obietnicy spełnienia własnych post-warunki (biorąc pod uwagę, że osoba dzwoniąca spełniła warunki wstępne). Zobacz na przykład: this article by Herb Sutter.

Nie kiedykolwiek napisać coś takiego:

try 
{ 
    //bug condition <== NO! Exceptions are not meant to handle bugs 
} 
catch() 
{ 
    //Remove file 
} 

ale raczej:

assert(/* bug condition... */); 

wracając do pytania:

Program jest zachowanie niezdefiniowane i najprawdopodobniej nie spowoduje żadnego wyjątku, gdy wykonasz:

char TempArray[10]; 
char c = TempArray[11]; 

Łapanie wszystkich wyjątków nie pomoże. Jest to błąd, tj. Błąd programowania programowanie i należy się upewnić, czy powinieneś obsługiwać błędy w sposób, który przenosi kontrolę do rutynowych procedur; co więcej, jeśli przyznajesz obecność błędów w swoim programie, czy nie mógłbyś po prostu przekazać kontroli do obsługi błędu? To może jeszcze bardziej pogorszyć sytuację.

Błędy powinny być rozwiązywane przez , zapobiegając im, korzystając z twierdzeń, być może stosując metodologie takie jak rozwój sterowany testami i tak dalej.

To powiedział, jeśli chodzi o sposób, aby złapać wszystkie wyjątki, można zrobić:

try 
{ 
    // ... 
} 
catch (...) // <== THIS WILL CATCH ANY EXCEPTION 
{ 
} 

Ale używając catch (...) jest zalecane jako wytyczne projektowania, ponieważ łatwo prowadzi do przełknięcia warunki błędach, które mają być obsługiwane i zapomnij o nich. W końcu wymyślono wyjątki, aby uniemożliwić programistom zapominanie o sprawdzaniu kodów błędów, a catch (...) czyni to tak łatwym.

Dla celów catch-wszystko, to byłoby lepiej niech wszystkich wyjątków pochodzą z std::exception, a następnie wykonaj:

try 
{ 
    // ... 
} 
catch (std::exception& e) 
{ 
    // Do something with e... 
} 
+4

* "Ale to jest uważane za zły styl programowania" *. Tylko dlatego, że mechanizm może być nadużywany, nie czyni go złym stylem programowania z definicji. Istnieje wiele ważnych przypadków użycia dla 'catch (...)', jest tylko złe, jeśli używasz go do ślepego ukrywania problemów, które nie powinny być ukryte. –

+0

Należy również zauważyć, że jeśli zostanie umieszczony na końcu, będzie podobny do 'else' w dużym bloku' if-else if-else'. – Rapptz

+0

@Niels: Cóż, chociaż mogą istnieć ważne zastosowania (ponieważ mogą istnieć ważne zastosowania 'using namespace std'), nadużywanie jest łatwiejsze niż nie. A "catch (...)" po prostu ułatwia zapomnienie o warunkach błędu –

0

Twój kod próbuje uzyskać dostęp do danych poza zdefiniowanymi granicami, co jest cała esencja jest całkowicie ważną rzeczą do podjęcia próby. W zależności od sytuacji i kompilatora, kod może, ale nie musi, ulec awarii z naruszeniem/uszkodzeniem dostępu, najprawdopodobniej nie. Z całą pewnością nie spowoduje to wyjątku - w wyjątkach C++ są one generowane tylko jawnie przez kod, a nie przez system, to po prostu zawiesza się, jeśli pójdzie źle, w przeciwieństwie do języków wyższych poziomów, takich jak Java i C#.

Składnia catch(...) będzie przechwytywała każdy możliwy wyjątek, ale nie ma to zastosowania w tej sytuacji.

2

To, czego chcesz użyć, to RAII. W takim przypadku utwórz klasę, która w konstruktorze przyjmuje nazwę pliku iw destruktorze kasuje plik. Przed zrobieniem czegokolwiek z plikiem, należy utworzyć obiekt takiej klasy o odpowiedniej nazwie i później, jeśli z jakiegoś powodu funkcja ta zostanie zamknięta (czysto lub za pomocą wyjątku), plik zostanie usunięty.

Przykładowy kod:

class FileGuard : public boost::noncopyable { 
    std::string filename_; 

    public: 
    FileGuard(const std::string &filename) : filename_(filename) 
    {} 

    ~FileGuard() 
    { 
     ::unlink(filename_); 
    } 
} 
+0

Myślę, że teraz przeskakujesz zbyt wiele rozdziałów przed TS;) –

+1

Najprawdopodobniej tak, ale IMO jest ważne, aby przedstawić go do idei RAII tak wcześnie, jak to możliwe. :-) – anydot

+0

W pewnym sensie jest to interesujące pytanie dotyczące "tego, czego RAII nie można naprawić": Niezdefiniowane zachowanie (char TempArray [10], char c = TempArray [11];) i zapisywanie poufnych informacji poufnych w pliku fizycznym (Komputer może być odłączony, itp.) –

0

C++ pozwala pracować bezpośrednio z pamięci i jest częściowo C kompatybilne. Składnia próbujesz użyć:

char some_array[10]; 

niby C składni, nie C++ i

char c = some_array[11]; 

jest surowy dostęp do pamięci. To jest unexpected behavior. Oznacza to, że nikt nie powie ci, co się wydarzy. Może po prostu dostaniesz niewłaściwą postać i być może program zostanie zabity przez system operacyjny. Albo księżyc spadnie na Ziemię. =)

Jeśli chcesz funkcji wysokiego poziomu - użyj czystego C++. Spójrz na standardową bibliotekę zamiast tablic "C". Możesz użyć metody std::vector za pomocą metody at (size_type n), aby uzyskać wyjątek out_of_range - tak, jak potrzebujesz.

+0

Kontenery nie wyrzucają wyjątków 'out_of_range' w analogicznym przypadku. Zazwyczaj do tego celu potrzebne są metody 'at()'. – juanchopanza

+0

@juanchopanza, tak, na pewno masz rację. Po prostu zapomniałem o tym wspomnieć. Naprawię ten post. Dzięki. – JustAnotherCurious

0

Podobnie jak inne odpowiedzi, nie można poprawnie rozwiązać tego problemu z natywnym, standardowym C++. Rzeczywiście, próbowanie zrobienia czegoś po raz undefined behaviour jest zwykle naprawdę złe. Jeśli nie wiesz, w jakim stanie jest Twoja aplikacja, w jaki sposób możesz bezpiecznie uruchomić kod? Po prostu zawieść szybko.

Właściwym sposobem na rozwiązanie problemu jest posiadanie kolejnego, oddzielnego procesu "nadzorującego", który przeprowadzi oczyszczenie. Jest to dość proste - wystarczy, że proces monitorowania stale monitoruje istnienie pliku. Kiedy się pojawi, proces watchdog powinien go usunąć. To usuwanie będzie działać dopóki nie pojawi się ostatnie odniesienie do pliku, a następnie dokona usunięcia [on * nix OS spowoduje zmianę nazwy pliku na tymczasowe miejsce, na systemach Win będzie czekało, aż plik nie będzie odwoływał się]. Po zakończeniu programu głównego z plikiem - za pomocą normalnych metod lub awarii lub innego podobnego systemu, system operacyjny usunie go poprawnie.

0

Jeśli chcesz się upewnić, że Twój "prywatny" plik jest zawsze usuwany, to może to oznaczać program "opakowujący".

Utwórz nową aplikację, która uruchamia chronioną aplikację, a następnie czeka na jej zakończenie.Kiedy się zakończy (to jest awarie lub czyste wyjście), usuń swój prywatny plik, a następnie zakończ.

Zamiast uruchamiać aplikację, należy uruchomić opakowanie.

int main(void) 
{ 
    int processId = exec("your protected app"); 

    WaitForProcessExit(processId); 

    _unlink("protectedfile.bin"); 

    return 0;   

}