To jak powinien poprawnie wygladać ten kod
CMyObject *pObj = new CMyObject();
pObj->MyMetyhod();
pObj = NULL;
delete pObj;
i czemu tam sie wyciek pojawi?
To jak powinien poprawnie wygladać ten kod
CMyObject *pObj = new CMyObject();
pObj->MyMetyhod();
pObj = NULL;
delete pObj;
i czemu tam sie wyciek pojawi?
To chyba oczywiste: nie zwalniamy pamięci zaalokowanej na obiekt, bo zanim tą pamięć zwolnimy tracimy wskaźnik na nią (bo przypisujemy mu NULL). Nalezy zamienić dwie ostatnie linijki miejscami...
niezalogowany napisał(a)
To jak powinien poprawnie wygladać ten kod
CMyObject *pObj = new CMyObject();
pObj->MyMetyhod();
pObj = NULL;
delete pObj;
i czemu tam sie wyciek pojawi?
Shalom napisał(a)
To chyba oczywiste: nie zwalniamy pamięci zaalokowanej na obiekt, bo zanim tą pamięć zwolnimy tracimy wskaźnik na nią (bo przypisujemy mu NULL). Nalezy zamienić dwie ostatnie linijki miejscami...
Innymi słowy Panu podziękujemy ;-P
murzynarktyczny napisał(a)
Krolik napisał(a)
BTW: co do powyższego zadania to oprócz tych 2 błędów, ja bym jeszcze dodał, że używanie makra NULL w C++ to jest "bad style", bo jest zwyczajnie niepotrzebne. Używa się 0. Makro NULL w C++ zwyczajnie nie ma sensu, bo jedyna jego możliwa definicja to:
#define NULL 0
>
> Lol. Idąc dalej za tą filozofią, WSZYSTKO to syntactic sugar i należy pisać tylko z goto.
> 0 - wartość liczbowa.
> NULL - pusty adres.
> I tak należy pisać. Informujesz wtedy czytającego, co przypisujesz. C++ nie wspiera 'wartości pustej' bezpośrednio - więc to właśnie kwestia dobrego stylu.
>
>
```cpp
Klasa {
X *y;
int z;
...
}
jakasMetoda() {
y = NULL; //automatycznie po przeczytaniu - aha, y to wskaznik - jesli chce wiecej szczegolow, najezdzam na nazwe myszką
z = 0; //aha, z to typ liczbowy
}
Podobna sprawa jest z asciiz - dobrym stylem jest pisanie rzeczy w stylu
x[0] = '\0';
zamiast = 0. Ale jeśli zakres jest bardzo mały i deklaracja jest blisko często to olewam.
Problem w tym, że NULL to makro, a nie konstrukcja językowa jak '\0'. I wiążą się z tym wszystkie niebezpieczeństwa używania makr - np. brak jakiegokolwiek wsparcia dla przestrzeni nazw. Kompilator też nie rozróżnia NULL od 0. Dodatkowo możesz mieć poważny problem, gdy ktoś Ci nagle dołączy do projektu jakiś stary header żywcem z C, gdzie była stara definicja #define NULL (void*) 0, i pół programu w C++ nagle przestanie się kompilować. Przy używaniu różnych bibliotek z różnych źródeł bezpieczniej w kodzie C++ wszędzie pisać 0 (zresztą tak zaleca Soustroup w Klasyce C++). Być może czytelność jest nieznacznie większa, ale i tak przed niczym Cię to NULL nie chroni tj. i tak możesz w swoim kodzie napisać:
jakasMetoda() {
y = 0; // wskaźnik nullowy
z = NULL; //przypisujemy zwykłe (int) 0 do zmiennej
}
i wszystko się dalej pięknie kompiluje. Raczej wprowadzasz złudne poczucie bezpieczeństwa takim kodem.
Sami widzicie ile można powiedzieć na temat głupich 4 linijek kodu. ;-P
Linijki były spoko. Mnie chodziło tylko o samo . zamiast ->, że to już jest niemal jak literówka. Ale już kwestia leaku była jak najbardziej ok.
Swoją drogą ostatnio też przyszedł mi do głowy fajny przykład z życia wzięty:
class CyclicBuffer {
private:
char* buffer;
size_t length;
size_t startPos;
size_t endPos;
public:
// ... różne duperele jak konstruktory, inicjalizacja danych
void addToBuffer(char* data, size_t count);
};
void CyclicBuffer::addToBuffer(char* data, size_t count) {
if (startPos <= endPos) {
// tu kilkanaście linijek długiego kodu, napisanego niezbyt porządnie
}
}
Co jest źle w tej metodzie?
brak ; po } zamykającym deklaracji klasy? Czy to tylko twoja literówka? :D
Ach, wiedziałem, że ktoś znajdzie głupią literówkę. Sorry. Już poprawiam. Nie o to chodzi.
Zresztą ten kod równie dobrze można napisać w Javie czy C#.
Pytanie testuje, czy ktoś:
Punkt 1. należy do wiedzy podstawowej - ktoś kto nie zna podstawowych struktur danych i nie rozumie jak działają hashmapa, wektor, lista łączona czy właśnie bufor cykliczny, nie ma czego szukać w programowaniu. Chyba, że chce całe życie klepać formatki wyświetlające dane z bazy wg tego co zaprojektował projektant.
Zauważyłem też, że punkt 2. jest zaskakująco rzadko spotykaną umiejętnością, a bardzo przydatną. Wielu programistów skupia się na mało istotnych szczegółach, nie widząc wielkiego fuckupu w podstawowej funkcjonalności.
BTW: W zadaniu NIE MA HACZYKA. Zadanie pochodzi z prawdziwego projektu i błąd jest autentyczny.
W ogóle ten projekt dał mi bardzo dużo przykładów na zadania dla kandydatów. Bardzo nie lubię dostawać do rozwiązania problemów "wydumanych", przygotowanych specjalnie żeby zagiąć kandydata. ;]
W cyklicznym to raczej nie można założyć, że początek będzie przed końcem.
IMO powinno być != zamiast <=
@Loloki: źle, próbuj dalej.
Ot chocby brak sprawdzenia czy ten ciąg znaków sie zmieści do bufora, ale to raczej nie to, bo przeciez w tej funkcji moze być nowa alokacja pamięci.
Jest sprawdzanie w tej części co napisałem // dużo linijek kodu.
Załóżmy, że ta część jest poprawna. Tzn. też była błędna [rotfl], ale nie umieściłem, bo nie to jest fajnego w tym zadaniu.
sprawdzenie czy <= zezwala na równość - gdy start==end, to nie wiadomo czy bufor jest pusty czy pełny i nie wiadomo czy można zapisywać. Powinno być < - warto zachować przynajmniej jeden znak pusty dla pewności.
Jesli start <= end to nalezaloby jakos przekrecic startPos, w innnym przypadku metoda zawsze bedzie w tym miejscu zwracac false i wychodzic, nic wiecej nie robiac.
@nav = bufory cykliczny nigdy nie jest pelny, zapetla sie i nadpisuje od poczatku. Tak mi sie przynajmniej wydaje ;d
// zalezy co chcesz osiagnac - moze nie chcesz wersji ktora nadpisuje dane - n
Jak nie chcesz nadpisac to po co cykliczny? Lepiej wtedy producent konsumer czy podobne, i jak konsumer odczyta to reset.
Bylo ostrzezenie o off-topicu, goodbye.