2013-02-06 9 views
10

Pracuję nad dynamicznie połączoną biblioteką (DLL) o krytycznym działaniu, która również powinna mieć stosunkowo mały rozmiar binarny. Ponieważ nie jawnie rzuca żadnych wyjątków, chciałbym wyłączyć obsługę wyjątków w ogóle. Jest jednak jeden wyjątek (niezamierzony kalambur): kiedy zabraknie pamięci (OOM), muszę zgłosić kod błędu do aplikacji, aby miał szansę poradzić sobie z wdziękiem. Baza kodu jest zbyt duża, aby sprawdzić każdą alokację indywidualnie i propagować błąd oraz zawiera zewnętrzny kod, którego nie powinienem dotykać. Dlatego chciałbym przechwycić wyjątki OOM w wyeksportowanych funkcjach moich bibliotek DLL.Jak zapewnić odporność na brak pamięci przy wyłączonych wyjątkach C++ (VS2010)?

Szybki test pokazuje, że po wyłączeniu wyjątków C++ w Visual C++ 2010 (tj. Flagi nie/EHa,/EHsc lub/EHs), nadal przeskakuje do bloku catch (std :: bad_alloc &) przy przydzielaniu zbyt dużej ilości pamięci .

Wygląda na to, że działa zgodnie z oczekiwaniami. Jednak otrzymuję następujące ostrzeżenie na poziomie 1: "Używany program obsługi wyjątków C4530: C++, ale semantykę odwijania nie włączono." Określ/EHsc ". MSDN twierdzi, że "obiekt z automatycznym przechowywaniem w ramce, między funkcją wykonującą rzut i funkcją rzucającą rzut, nie zostanie zniszczony".

Dokładnie, co bym tu stracił? W porządku jest pozostawienie rzeczy w stanie niezdefiniowanym, o ile wszystko, co zostało utworzone przez bibliotekę, może zostać usunięte, a aplikacja może zacząć od początku (jeśli tak wybierze). Czy istnieje duże ryzyko wycieku pamięci, której nie można odzyskać?

Czy biblioteki DLL używają oddzielnej puli pamięci? A jeśli tak, czy mogę go usunąć bez konieczności usuwania aplikacji z biblioteki DLL? Mogę z łatwością sprawić, że moja biblioteka zignoruje jakiekolwiek dalsze (wyeksportowane) wywołania funkcji, dopóki aplikacja nie wykona reinicjalizacji.

Dzięki za porady.

+0

* Czy biblioteki DLL używają oddzielnej puli pamięci? * Http://stackoverflow.com/questions/10820114/do-statically-linked-dlls-use-a-different-heap-than-the-main-program – thang

+0

* A jeśli tak, czy mogę go usunąć bez konieczności usuwania aplikacji z biblioteki DLL? * Tak, po prostu usuń rzeczy z nowego i uwolnij rzeczy z malloc. – thang

+1

Brak obsługi wyjątków oznacza, że ​​obiekty utworzone na stosie (i wewnątrz konstruktora, który się nie powiedzie) nie zostaną zniszczone. Jeśli masz zamiar wyjść, gdy dzieje się 'bad_alloc', to dobrze z tym, jak sądzę [dopóki nie masz dziwnych zasobów, które nie zostaną wyczyszczone przy wyjściu z programu - ale większość powinna]. Jeśli chcesz "kontynuować" po 'bad_alloc', kod będzie musiał śledzić obiekty i zniszczyć wszystkie obiekty utworzone w ramkach stosu pomiędzy' throw' i 'catch'. Możesz eksperymentować, pisząc mały kod, który ma wydruki w destruktorach. –

Odpowiedz

1

Kilka eliminacje:

ja nie wiem, czy rzuca wyjątek bez obsługi wyjątków włączona jest niezdefiniowane zachowanie lub nie w normie, ale nie są z pewnością dostanie stos wywołań odwijania/spalające z obiektami na stosie.

Jeśli piszesz kod w stylu C++ za pomocą RAII dla muteksów, plików, pamięci itd., To bardzo zła rzecz.

Przechodząc następnie, i zakładając, że kod jest zasadniczo kod C-style:

1) Jeśli statycznie łączenie do biblioteki C Runtime, Twój DLL nie będą dzielić sterty z głównym aplikacji. Rozładowanie biblioteki DLL powinno zwolnić wyciek pamięci - ale ponownie należy zadbać o inne zasoby.

2) Jeśli dynamicznie łączysz się z środowiskiem wykonawczym C (dość powszechnym), to dzielisz stertę. Będziesz musiał mieć sposób ręcznego zwolnienia dowolnej pamięci przydzielonej z biblioteki DLL.

Posiadanie siebie zbytnio zaśmiecone problemami związanymi z biblioteką DLL, poleciłbym szybką analizę porównawczą, aby sprawdzić, za co płacisz, jeśli chodzi o włączanie wyjątków. W zależności od platformy i kompilatora wyjątki niekasowane mogą mieć bardzo niewielki wpływ na wydajność.

+0

To nie jest kod w stylu C, a znaczna jego część nie jest pod moją kontrolą. Chociaż ufam temu kodowi strony trzeciej podczas normalnego działania, kiedy zgłoszony zostanie wyjątek OOM, nie sądzę, żebym mógł przyjąć jakiekolwiek założenia, niezależnie od tego, czy obsługa wyjątków jest włączona. "Będziesz musiał mieć sposób ręcznego zwolnienia pamięci przydzielonej z biblioteki DLL." Właśnie o to mi chodzi. :-) –

+0

Przepraszam, ale myślę, że tak naprawdę nie ma sposobu, aby zrobić to, co chcesz. Aby uzyskać "ręczne zwolnienie z biblioteki DLL" w moich własnych systemach typu wtyczki, wymagam, aby cały kod klienta był przydzielany przy użyciu niestandardowej procedury alokacji, którą moje podstawowe materiały dostarczane są do biblioteki DLL. To powiązanie pozwala rdzeniu upuścić bibliotekę DLL tak, jak chcesz. Ale jeśli nie możesz wymusić tego samemu, to nie sądzę, żeby to można było zrobić. – Stephen

Powiązane problemy