C assert.h i malloc

0

hej. jak to w końcu jest z tym assert,h i niespodziewanym błędami typu np. NULL z malloc ?
czytałam sobie implementację vectora w C i widzę, że gość to tak stosował
http://codingrecipes.com/implementation-of-a-vector-data-structure-in-c w związku z czym sama zaczęłam

ptr = malloc(sizeof(nof_s * sizeof(char*)));
assert(ptr!=NULL);

teraz zaś przypadkowo (szukałam czegoś innego) trafiam na http://stackoverflow.com/questions/1963626/how-to-use-a-c-assert-to-make-the-code-more-secure
So, there is a BIG difference between the two examples. For things like checking the return value of malloc, assert is wrong because there is no guarantee that they will return non-NULL, and as I have mentioned above, assert(x) means "I am completely sure x is true", and not just "If x is not true, it is bad". For this, one uses if(x) good(); else bad(); control.
już sama nie wiem.

1

Kiedy stosować asercje:

  • przede wszystkim do debugowania kodu. Ja w swoim kodzie czasami nakładam assert-y na indeksy przy indeksowaniu tablicy/wektora. Oczywiście rzecz dyskusyjna. Dobry debugger wychwyci przekroczenie zakresów.
  • w testach jednostkowych (np w gtest/gmock ASSERT_EQ i pokrewne)
  • dla pre-conditionali i post-conditionali metod/funkcji. Np kiedy dostajemy ileś tam parametrów i specyfikacja mówi wyraźnie, że każdy z nich MUSI spełniać pewne ograniczenia (pFoo != NULL, pBar > 0 itp) a użytkownik funkcji ma obowiązek zadbać o poprawne wartości. Zamiast drabinki if-ów lepiej IMO dać sekewncje assert-ów.

Kiedy nie stosować asercji:

  • sprawdzenie jest częścią logiki, nie spełnienie warunku MOŻE się przytrafić i nie powinno kończyć programu
  • kiedy sprawdzenie warunku powinno pozostać w kodzie produkcyjnym. Najczęściej dąży się do tego żeby wszystkie assert-y zostały usunięte przez kompilator w wersji release ustawiając makro NDEBUG.

Oczywiście w sytuacji braku pamięci powinniśmy tak czy siak zamknąć aplikacje więc na pierwszy rzut oka asercja wydaje się niegłupia.
Jednak pisząc assert(ptr!=NULL) naszą intencją jest by ten warunek zniknął w wersji release.
My jednak chcemy zawsze takie coś testować. Z tego powodu ja dałbym if-a.

0

Dzięki za merytoryczną odpowiedź. Już sama przegrzebałam o tym internet, kończąc na tym, że rozwiązania typu xmalloc są dla leniwych programistów GNU i generalnie w bibliotekach należy unikać konstrukcji ala:

ptr = malloc(sizeof(nof_s * sizeof(char*)));
if(!ptr) {
	perror("malloc failed\n");
	exit(EXIT_FAILURE):
}

może pozmieniam, ale też trudno mi będzie zrobić żeby górna biblioteczna funkcja zwróciła błąd nie przerywając działania. jestem początkująca.

ptr = malloc(sizeof(nof_s * sizeof(char*)));
if(!ptr) {
	perror("malloc failed\n");
	return -1;
}
1

Szkoda zachodu sprawdzać malloca, jeśli jedynym rezultatem błędu ma być wyjście z aplikacji. I tak się wywali przy próbie użycia tego wskaźnika.

Poza tym alokacja może się nie powieźć właściwie w dwóch przypadkach:
a) system embedded z bardzo ograniczoną pamięcią
b) alokacja wielkiego obszaru (rzędu gigabajtów)

Jeśli na normalnym komputerze nie powiedzie się malloc dla marnych kilku kilobajtów, to większa szansa że zaraz cały system wyleci z bluescreenem i i tak nic na to nie poradzimy.

0

@Azarien po prostu znalazłam takie wypowiedzi

http://stackoverflow.com/questions/9050616/c-api-design-what-to-do-when-malloc-returns-null
//If allocation fails in a way that prevents forward progress, the only acceptable solution for library code is to back-out whatever allocations and other changes have already been made in the partially-completed operation and return a failure code to the caller. Only the calling application can know what the right way to proceed is. Some examples:

A music player might just abort or return to an initial/stopped state and wait for user input again.
A word processor might need to store an emergency dump of the current document state to a recovery file then abort.
A high-end database server might need to reject and back out the whole transaction and report to the client.
If you follow the oft-advised but backwards idea that your library should just abort the caller on allocations failures, you will either have many programs that determine they cannot use your library for this reason, your users' of the programs that use your library will be extremely angry when an allocation failure causes their valuable data to be thrown away.

Edit: One objection some of the "abort" camp will raise against my answer is that, on systems with overcommit, even calls to malloc that appeared to succeed may fail when the kernel tries to instantiate physical storage for the virtual memory allocated. This ignores the fact that anyone needing high reliability will have overcommit disabled, as well as the fact that (at least on 32-bit systems) allocation failure is more likely due to virtual address space exhaustion than physical storage exhaustion.//

http://stackoverflow.com/questions/7590254/what-is-the-difference-between-xmalloc-and-malloc
//xmalloc is not part of the standard library. It's usually the name of a very harmful function for lazy programmers that's common in lots of GNU software, which calls abort if malloc fails. Depending on the program/library, it might also convert malloc(0) into malloc(1) to ensure that xmalloc(0) returns a unique pointer.

In any case, aborting on malloc failure is very very bad behavior, especially for library code. One of the most infamous examples is GMP (the GNU multiprecision arithmetic library), which aborts the calling program whenever it runs out of memory for a computation.

Correct library-level code should always handle allocation failures by backing out whatever partially-completed operation it was in the middle of and returning an error code to the caller. The calling program can then decide what to do, which will likely involve saving critical data.//

EDIT: dopiero teraz zauważyłam zedytowaną odp. Dzięki

1 użytkowników online, w tym zalogowanych: 0, gości: 1