Ustawianie zmiennej NA NULL po free

W mojej firmie istnieje reguła kodowania, która mówi, że po zwolnieniu dowolnej pamięci, zresetuj zmienną do NULL. Na przykład ...

void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}

Uważam, że w przypadkach takich jak kod pokazany powyżej, ustawienie na NULL nie ma żadnego znaczenia. Czy coś przeoczyłem?

Jeśli nie ma sensu w takich przypadkach, zamierzam podjąć się tego z "zespołem jakości", aby usunąć tę regułę kodowania. Proszę o radę.

Author: ashwani, 2009-06-22

23 answers

Ustawienie nieużywanych wskaźników na NULL jest stylem defensywnym, chroniącym przed zwisającymi błędami wskaźnika. Jeśli zwisający wskaźnik jest dostępny po jego zwolnieniu, możesz odczytać lub zastąpić pamięć losową. Jeśli dostępny jest wskaźnik null, na większości systemów pojawia się natychmiastowa awaria, informująca od razu o błędzie.

Dla zmiennych lokalnych może to być trochę bezcelowe, jeśli jest "oczywiste", że wskaźnik nie jest już dostępny po zwolnieniu, więc ten styl jest bardziej odpowiedni dla dane członków i zmienne globalne. Nawet w przypadku zmiennych lokalnych, może to być dobre podejście, jeśli funkcja jest kontynuowana po zwolnieniu pamięci.

Aby ukończyć styl, należy również zainicjować wskaźnik NA NULL, zanim zostanie im przypisana prawdziwa wartość wskaźnika.

 256
Author: Martin v. Löwis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 05:40:26

Ustawianie wskaźnika na NULL po free jest wątpliwą praktyką, która jest często spopularyzowana jako zasada "dobrego programowania" na ewidentnie fałszywej przesłance. Jest to jedna z tych fałszywych prawd, które należą do kategorii "brzmi dobrze", ale w rzeczywistości nie osiągają absolutnie nic użytecznego (i czasami prowadzi do negatywnych konsekwencji).

Rzekomo ustawienie wskaźnika na NULL po free ma zapobiec problemowi "double free", gdy ta sama wartość wskaźnika zostanie przekazana do free więcej niż raz. W rzeczywistości jednak, w 9 przypadkach na 10 rzeczywisty problem "double free" występuje, gdy różne obiekty wskaźnika posiadające tę samą wartość wskaźnika są używane jako argumenty dla free. Nie trzeba dodawać, że ustawienie wskaźnika na NULL po free nie daje absolutnie nic, aby zapobiec problemowi w takich przypadkach.

Oczywiście można napotkać problem "double free" przy użyciu tego samego obiektu wskaźnika jako argumentu do free. W rzeczywistości jednak takie sytuacje zwykle oznacza problem z ogólną strukturą logiczną kodu, a nie zwykły przypadkowy "podwójny wolny". Właściwym sposobem radzenia sobie z problemem w takich przypadkach jest przegląd i ponowne przemyślenie struktury kodu, aby uniknąć sytuacji, gdy ten sam wskaźnik jest przekazywany do free więcej niż jeden raz. W takich przypadkach ustawienie wskaźnika na NULL i rozważenie problemu "naprawione" jest niczym innym jak próbą zamiatania problemu pod dywan. To po prostu nie będzie działać w ogólnym przypadku, ponieważ problem ze strukturą kodu zawsze znajdzie inny sposób, aby się zamanifestować.

Wreszcie, jeśli twój kod jest specjalnie zaprojektowany tak, aby polegać na wartości wskaźnika NULL LUB NIE NULL, idealnie jest ustawić wartość wskaźnika na NULL po free. Ale jako ogólna zasada " dobrej praktyki "(jak w" zawsze ustaw wskaźnik na NULL po free") jest to, po raz kolejny, dobrze znana i dość bezużyteczna podróbka, często po której następują niektóre z czysto religijnych, podobnych do voodoo powodów.

 37
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-07 05:08:53

Większość odpowiedzi skupiła się na zapobieganiu podwójnemu wolnemu, ale ustawienie wskaźnika na NULL ma inną korzyść. Po zwolnieniu wskaźnika pamięć ta jest dostępna do ponownego przydzielenia przez kolejne wywołanie do malloc. Jeśli nadal masz oryginalny wskaźnik wokół ciebie może skończyć się błędem, w którym próbujesz użyć wskaźnika po uwolnieniu i uszkodzeniu innej zmiennej, a następnie twój program wchodzi w Nieznany stan i mogą się zdarzyć wszelkiego rodzaju złe rzeczy (awaria, jeśli masz szczęście, data korupcja, jeśli masz pecha). Jeśli Ustawiłeś wskaźnik NA NULL po free, każda próba odczytu/zapisu przez ten wskaźnik później spowodowałaby segfault, co jest generalnie lepsze niż przypadkowe uszkodzenie pamięci.

Z obu powodów dobrym pomysłem może być ustawienie wskaźnika na NULL po free (). Nie zawsze jest to konieczne. Na przykład, jeśli zmienna wskaźnika wychodzi poza zakres natychmiast po free(), nie ma powodu, aby ustawić ją na NULL.

 31
Author: Mike McNertney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 07:28:55

Jest to uważane za dobrą praktykę, aby uniknąć nadpisywania pamięci. W powyższej funkcji jest niepotrzebna, ale często po jej wykonaniu może znaleźć błędy aplikacji.

Spróbuj czegoś takiego zamiast:

#if DEBUG_VERSION
void myfree(void **ptr)
{
    free(*ptr);
    *ptr = null;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = null; } while (0)
#endif

DEBUG_VERSION umożliwia tworzenie profili w kodzie debugowania, ale oba są funkcjonalnie takie same.

Edytuj: dodano do ... chociaż zgodnie z sugestią poniżej, dzięki.

 15
Author: razzed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-13 01:43:00

Jeśli osiągniesz wskaźnik, który był wolny () d, może się złamać lub nie. Pamięć ta może zostać ponownie przydzielona do innej części programu, a następnie zostanie uszkodzona,

Jeśli ustawisz wskaźnik na NULL, to jeśli uzyskasz do niego dostęp, program zawsze zawiesza się z segfault. Nigdy więcej,, czasami to działa", nigdy więcej,, wywala się w nieprzewidywalny sposób". O wiele łatwiej jest debugować.

 7
Author: Tadeusz A. Kadłubowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 06:10:35

Ustawienie wskaźnika na pamięć free'D oznacza, że każda próba dostępu do tej pamięci przez wskaźnik będzie natychmiast zawieszana, zamiast powodować nieokreślone zachowanie. To znacznie ułatwia ustalenie, gdzie coś poszło nie tak.

Widzę Twój argument: ponieważ nPtr jest poza zasięgiem zaraz po nPtr = NULL, nie ma powodu, aby ustawić go na NULL. Jednak w przypadku struct członka lub gdzie indziej, gdzie wskaźnik nie wychodzi natychmiast poza zakres, to to ma sens. Nie jest od razu jasne, czy ten wskaźnik zostanie ponownie użyty przez kod, który nie powinien go używać.

Prawdopodobnie reguła jest podana bez rozróżniania tych dwóch przypadków, ponieważ znacznie trudniej jest automatycznie wyegzekwować regułę, nie mówiąc już o przestrzeganiu jej przez deweloperów. Nie zaszkodzi ustawić Wskaźniki na NULL po każdym wolnym, ale ma potencjał Wskazywania dużych problemów.

 7
Author: Jared Oberhaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-23 21:50:07

Najczęstszym błędem w c jest double free. Zasadniczo robisz coś takiego

free(foobar);
/* lot of code */
free(foobar);

I kończy się dość źle, OS próbuje uwolnić trochę już zwolnionej pamięci i ogólnie to segfault. Więc dobrą praktyką jest ustawienie NULL, więc możesz przetestować i sprawdzić, czy naprawdę potrzebujesz zwolnić tę pamięć

if(foobar != null){
  free(foobar);
}

Należy również zauważyć, że free(NULL) nic nie zrobi, więc nie musisz pisać instrukcji if. Nie jestem naprawdę Guru OS, ale jestem ładna nawet teraz większość osów by crash na double free.

To również główny powód, dla którego wszystkie języki z garbage collection (Java, dotnet) były tak dumne, że nie miały tego problemu, a także nie musiały zostawiać programistom zarządzania pamięcią jako całości.

 7
Author: RageZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 07:45:41

Ideą stojącą za tym, jest powstrzymanie przypadkowego ponownego użycia uwolnionego wskaźnika.

 6
Author: Mitch Wheat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 05:39:17

To (może) być naprawdę ważne. Chociaż zwalniasz pamięć, późniejsza część programu może przydzielić coś nowego, co stanie się lądować w przestrzeni. Twój stary wskaźnik wskazuje teraz na prawidłowy fragment pamięci. Jest wtedy możliwe, że ktoś użyje wskaźnika, co skutkuje nieprawidłowym stanem programu.

Jeśli ZERUJESZ wskaźnik, to każda próba jego użycia spowoduje dereferencję 0x0 i awarię właśnie tam, co jest łatwe do debugowania. Losowe wskaźniki wskazujące na losowe pamięć jest trudna do debugowania. Oczywiście nie jest to konieczne, ale dlatego jest to w dokumencie dotyczącym najlepszych praktyk.

 4
Author: Steven Canfield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 05:40:53

Ze standardu ANSI C:

void free(void *ptr);

Funkcja swobodna powoduje spację wskazywany przez ptr do dealokacji, czyli udostępniane do dalszego przydział. Jeśli ptr jest wskaźnikiem null, nie występuje żadne działanie. W przeciwnym razie, jeśli argument nie pasuje do wskaźnika wcześniej zwrócony przez calloc , malloc, czyli funkcja realloc, lub jeśli przestrzeń została dealokowana przez call to free or realloc, the behavior jest nieokreślona.

"undefined behavior" jest prawie zawsze awaria programu. Aby tego uniknąć, bezpiecznie jest zresetować wskaźnik NA NULL. sama funkcja free() nie może tego zrobić, ponieważ jest przekazywana tylko wskaźnik,a nie wskaźnik do wskaźnika. Możesz również napisać bezpieczniejszą wersję free (), która NULLs wskaźnik:

void safe_free(void** ptr)
{
  free(*ptr);
  *ptr = NULL;
}
 4
Author: Vijay Mathew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 07:18:47

Uważam to za mało pomocne, ponieważ z mojego doświadczenia, gdy ludzie uzyskują dostęp do wolnej alokacji pamięci, prawie zawsze jest to spowodowane tym, że mają gdzieś inny wskaźnik. A potem koliduje z innym osobistym standardem kodowania, którym jest "unikanie niepotrzebnego bałaganu" , więc nie robię tego, ponieważ myślę, że rzadko pomaga i sprawia, że kod jest nieco mniej czytelny.

Jednak-nie ustawię zmiennej na null, jeśli wskaźnik nie ma być używany ponownie, ale często konstrukcja wyższego poziomu daje mi powód, aby ustawić go na null i tak. Na przykład, jeśli wskaźnik jest członkiem klasy i usunąłem to, co wskazuje na to "kontrakt", jeśli chcesz klasy jest to, że ten członek wskaże coś ważnego w dowolnym momencie, więc musi być ustawiony na null z tego powodu. Mała różnica, ale myślę, że ważna.

W c++ ważne jest, aby zawsze myśleć, kto posiada te dane, gdy przydzielasz trochę pamięci (chyba, że używasz inteligentnych wskaźników, ale nawet wtedy niektóre myśli jest wymagane). Proces ten prowadzi zazwyczaj do tego, że wskaźniki są na ogół członkami jakiejś klasy i generalnie chcesz, aby klasa była w prawidłowym stanie przez cały czas, a najprostszym sposobem na to jest ustawienie zmiennej członkowskiej na NULL, aby wskazać, że nie wskazuje teraz nic.

Powszechnym wzorcem jest ustawienie wszystkich wskaźników członkowskich na NULL w konstruktorze i wywołanie destruktora delete na wszystkich wskaźnikach do danych, które twój projekt mówi, że klasa posiada. Wyraźnie w tym przypadku masz aby ustawić wskaźnik na NULL, gdy usuniesz coś, aby wskazać, że wcześniej nie posiadasz żadnych danych.

Podsumowując, tak, często ustawiam wskaźnik NA NULL po usunięciu czegoś, ale jest to część większego projektu i myśli o tym, kto jest właścicielem danych, a nie ze względu na ślepe przestrzeganie standardowej reguły kodowania. Nie zrobiłbym tego w twoim przykładzie, ponieważ myślę, że nie ma z tego żadnych korzyści i dodaje "bałagan" , który z mojego doświadczenia jest tak samo odpowiedzialny za błędy i zły kod jak ten coś w tym stylu.

 4
Author: jcoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 08:11:12

Ostatnio natknąłem się na to samo pytanie po tym, jak szukałem odpowiedzi. Doszedłem do takiego wniosku:

Jest to najlepsza praktyka i trzeba jej przestrzegać, aby była przenośna we wszystkich systemach (embedded).

free() jest funkcją biblioteczną, która zmienia się wraz ze zmianą platformy, więc nie należy oczekiwać, że po przekazaniu wskaźnika do tej funkcji i po zwolnieniu pamięci wskaźnik ten zostanie ustawiony na NULL. Może nie być tak w przypadku niektórych bibliotek zaimplementowanych dla Peron.

Więc zawsze idź do

free(ptr);
ptr = NULL;
 4
Author: Jalindar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-20 05:48:31

Ta zasada jest przydatna, gdy próbujesz uniknąć następujących scenariuszy:

1) masz naprawdę długą funkcję ze skomplikowaną logiką i zarządzaniem pamięcią i nie chcesz przypadkowo użyć wskaźnika do usuniętej pamięci później w funkcji.

2) Wskaźnik jest zmienną klasy, która ma dość złożone zachowanie i nie chcesz przypadkowo użyć wskaźnika do usuniętej pamięci w innych funkcjach.

W Twoim scenariuszu to nie dużo sensu, ale gdyby funkcja miała się wydłużyć, mogłoby to mieć znaczenie.

Możesz twierdzić, że ustawienie go na NULL może później maskować błędy logiczne, lub w przypadku, gdy założysz, że jest poprawny, nadal zawieszasz się na NULL, więc to nie ma znaczenia.

Ogólnie radziłbym ustawić go na NULL, gdy uważasz, że jest to dobry pomysł, a nie zawracać sobie głowy, gdy uważasz, że nie jest tego wart. Zamiast tego skup się na pisaniu krótkich funkcji i dobrze zaprojektowanych klas.

 3
Author: i_am_jorf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 05:42:25

Aby dodać do tego, co powiedzieli inni, jedną z dobrych metod użycia wskaźnika jest zawsze sprawdzanie, czy jest on prawidłowym wskaźnikiem, czy nie. Coś w stylu:


if(ptr)
   ptr->CallSomeMethod();

Jawne oznaczanie wskaźnika jako NULL po zwolnieniu pozwala na tego rodzaju użycie w C / C++.

 2
Author: Aamir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 05:44:33

Może to być bardziej argument inicjujący wszystkie wskaźniki do NULL, ale coś takiego może być bardzo podstępnym błędem:

void other_func() {
  int *p; // forgot to initialize
  // some unrelated mallocs and stuff
  // ...
  if (p) {
    *p = 1; // hm...
  }
}

void caller() {
  some_func();
  other_func();
}

p kończy się w tym samym miejscu na stosie co poprzednia nPtr, więc może nadal zawierać pozornie ważny wskaźnik. Przypisanie do *p może nadpisać wszelkiego rodzaju niepowiązane rzeczy i doprowadzić do brzydkich błędów. Zwłaszcza jeśli kompilator inicjalizuje zmienne lokalne z zerem w trybie debugowania, ale nie włącza optymalizacji. Więc debug buduje Nie pokazuj żadnych oznak błędu podczas losowego wysadzania kompilacji...

 2
Author: sth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-22 05:59:46

Ustawienie wskaźnika, który właśnie został uwolniony, na NULL nie jest obowiązkowe, ale dobrą praktyką. W ten sposób można uniknąć 1)za pomocą freed pointa 2) free it towice

 2
Author: pierrotlefou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 07:14:52

Ustawienia wskaźnik NA NULL ma chronić przed tzw. double-free-sytuacją, w której funkcja free() jest wywoływana więcej niż raz dla tego samego adresu bez ponownego przydzielania bloku pod tym adresem.

Double-free prowadzi do niezdefiniowanego zachowania - Zwykle do uszkodzenia lub natychmiastowego awarii programu. Wywołanie funkcji free() dla wskaźnika NULL nie robi nic i dlatego jest gwarantowane jako Bezpieczne.

Więc najlepsza praktyka, chyba że teraz na pewno, że wskaźnik opuszcza zakres natychmiast lub bardzo szybko po tym, jak free() ustawia ten wskaźnik NA NULL tak, że nawet jeśli free() zostanie wywołane ponownie, to jest teraz wywoływane dla wskaźnika NULL i niezdefiniowane zachowanie jest unikane.

 2
Author: sharptooth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 07:16:09

Istnieją dwa powody:

Unikaj awarii podczas podwójnego uwalniania

napisany przez RageZ W duplikat pytania.

Najczęstszym błędem w c jest podwójny za darmo. Zasadniczo robisz coś takiego jak że

free(foobar);
/* lot of code */
free(foobar);

I kończy się dość źle, OS spróbować aby uwolnić część już uwolnionej pamięci i ogólnie to segfault. Więc dobra praktyka jest ustawiona na NULL, więc ty może przetestować i sprawdzić, czy naprawdę need to free pamięć Ta

if(foobar != null){
  free(foobar);
}

Należy również zauważyć, że free(NULL) nic nie zrobisz więc nie musisz napisz oświadczenie if. Nie jestem. naprawdę OS guru, ale jestem całkiem nawet teraz większość osów rozbije się na podwójnym za darmo.

To także główny powód, dla którego wszystkie języki ze śmieciami (Java, dotnet) był tak dumny, że nie mając ten problem, a także nie konieczność pozostawienia deweloperowi zarządzanie pamięcią jako całość.

Unikaj używania już uwolnionych pointers

napisany przez Martin V. Löwis W kolejna odpowiedź.

Ustawienie nieużywanych wskaźników na NULL jest stylu obronnym, chroniąc przed zwisające robale wskaźnikowe. Jeśli zwisający wskaźnik jest dostępny po jego zwolnieniu, możesz czytać lub nadpisywać losowe pamięć. Jeśli dostępny jest wskaźnik null, masz natychmiastowy wypadek na większości systemów, informując od razu, co błąd jest.

Dla zmiennych lokalnych może być trochę bez sensu, jeśli jest "oczywiste" , że wskaźnik nie jest dostęp już po uwolnieniu, więc ten styl jest bardziej odpowiedni dla dane członków i zmienne globalne. Parzyste dla zmiennych lokalnych może być dobrym podejście, jeśli funkcja jest kontynuowana po zwolnieniu pamięci.

Aby uzupełnić styl, należy również inicjalizuj wskaźniki NA NULL przed otrzymują prawdziwy wskaźnik wartość.

 2
Author: Georg Schölly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:17

Chodzi o to, że jeśli spróbujesz dereferować Nieaktualny wskaźnik po jego uwolnieniu, chcesz zawieść mocno (segfault), a nie cicho i tajemniczo.

Ale... bądź ostrożny. Nie wszystkie systemy powodują segfault, jeśli dereference NULL. Na (przynajmniej niektórych wersjach) AIX, *(int*) 0 == 0, a Solaris ma opcjonalną kompatybilność z tą funkcją AIX"."

 2
Author: Jaap Weel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-07 03:25:28

Do pytania pierwotnego: Ustawienie wskaźnika na NULL bezpośrednio po zwolnieniu zawartości jest kompletną stratą czasu, pod warunkiem, że kod spełnia wszystkie wymagania, jest w pełni debugowany i nigdy więcej nie zostanie zmodyfikowany. Z drugiej strony, defensywne NULLing wskaźnika, który został uwolniony, może być całkiem przydatne, gdy ktoś bezmyślnie dodaje nowy blok kodu pod free(), gdy konstrukcja oryginalnego modułu nie jest poprawna, a w jego przypadku-kompiluje-ale-nie-robi-tego-czego-chcę robaki.

w każdym systemie istnieje nieosiągalny cel, aby uczynić go najłatwiejszym do właściwego, a także nieredukowalny koszt niedokładnych pomiarów. W C oferujemy zestaw bardzo ostrych, bardzo mocnych narzędzi, które mogą stworzyć wiele rzeczy w rękach wykwalifikowanego pracownika i zadać różnego rodzaju metaforyczne obrażenia, gdy są niewłaściwie obsługiwane. Niektóre z nich są trudne do zrozumienia lub prawidłowego użycia. A ludzie, będąc naturalną niechęcią do ryzyka, robią irracjonalne rzeczy, takie jak sprawdzanie wskaźnika dla wartości NULL zanim zadzwonisz za darmo z nim…

problem pomiaru polega na tym, że ilekroć próbujesz podzielić dobro od mniej dobrego, im bardziej skomplikowany przypadek, tym bardziej prawdopodobne jest, że otrzymasz niejednoznaczny pomiar. Jeśli celem jest zachowanie tylko dobrych praktyk, to niektóre niejednoznaczne zostają wyrzucone z faktycznie kiepskimi. Jeśli twoim celem jest wyeliminowanie złego, to niejasności mogą pozostać z dobrem. Dwa cele, utrzymać tylko dobre lub wyeliminować wyraźnie złe, wydaje się być diametralnie sprzeczne, ale zwykle jest trzecia grupa, która nie jest ani jedną, ani drugą, niektóre z obu.

zanim zgłosisz sprawę do działu jakości, spróbuj przejrzeć bazę danych błędów, aby zobaczyć, jak często, jeśli w ogóle, nieprawidłowe wartości wskaźników powodowały problemy, które musiały zostać zapisane. Jeśli chcesz coś zmienić, zidentyfikuj najczęstszy problem w kodzie produkcyjnym i zaproponuj trzy sposoby zapobiegania temu problemowi

 2
Author: Bill IV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-26 23:53:56

Ponieważ masz zespół ds. zapewnienia jakości, pozwól, że dodam drobną kwestię dotyczącą QA. Niektóre zautomatyzowane narzędzia QA dla C znaczą przypisania do wolnych wskaźników jako " bezużyteczne przypisanie do ptr". Na przykład PC-lint/FlexeLint z programu Gimpel mówi tst.c 8 Warning 438: Last value assigned to variable 'nPtr' (defined at line 5) not used

Istnieją sposoby selektywnego tłumienia wiadomości, więc nadal możesz spełnić oba wymagania QA, jeśli twój zespół tak zdecyduje.

 1
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 07:50:21

Zawsze zaleca się zadeklarowanie zmiennej wskaźnikowej z NULL, np.

int *ptr = NULL;

Powiedzmy, ptr wskazuje na0x1000 adres pamięci. Po użyciu free(ptr), zawsze zaleca się anulowanie zmiennej wskaźnika, deklarując ponownie NULL . np.:

free(ptr);
ptr = NULL;

Jeśli nie zadeklarowano ponownie NULL , zmienna wskaźnika nadal wskazuje ten sam adres ( 0x1000), zmienna wskaźnika nazywa się zwisającą wskaźnik . Jeśli zdefiniujesz inną zmienną wskaźnika (powiedzmy, q) i dynamicznie przydzielisz adres do nowego wskaźnika, istnieje szansa, że nowa zmienna wskaźnika przyjmie ten sam adres (0x1000). Jeśli w tym przypadku użyjesz tego samego wskaźnika (ptr) i zaktualizujesz wartość pod adresem wskazywanym przez ten sam wskaźnik ( ptr), wtedy program zapisze wartość do miejsca, w którym q jest wskazywany (ponieważ p iq są wskazywane ten sam adres ( 0x1000)).

Np.

*ptr = 20; //Points to 0x1000
free(ptr);
int *q = (int *)malloc(sizeof(int) * 2); //Points to 0x1000
*ptr = 30; //Since ptr and q are pointing to the same address, so the value of the address to which q is pointing would also change.
 1
Author: pkthapa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-03 13:01:09

W skrócie: nie chcesz przypadkowo (przez pomyłkę) uzyskać dostępu do adresu, który uwolniłeś. Ponieważ, kiedy zwalniasz adres, pozwalasz, aby ten adres w stercie był przypisany do innej aplikacji.

Jednakże, jeśli nie ustawisz wskaźnika na NULL i przez pomyłkę spróbujesz go usunąć lub zmienić wartość tego adresu; nadal możesz to zrobić. ALE NIE COŚ, CO LOGICZNIE CHCIAŁBYŚ ZROBIĆ.

Dlaczego nadal mogę uzyskać dostęp do pamięci miejsce, które uwolniłem? Because: możesz mieć wolną pamięć, ale zmienna wskaźnika nadal zawiera informacje o adresie pamięci sterty. Jako strategię obronną, ustaw ją na NULL.

 1
Author: Ehsan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-23 21:13:59