• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

podwójne usunięcie pamięci

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
1,399 wizyt
pytanie zadane 26 stycznia w C i C++ przez TOWaD Mądrala (6,250 p.)

Wiem co, ale nie potrafię zrozumieć dlaczego, podmiana wskaźnika wywala program i jak to ominąć, by zwolnić nadmiarowa pamięć.

Otrzymuję komunikat  [w tym programie]

free(): double free detected in tcache 2

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737348187968) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.

tak jakby podwójne wywołanie destruktora.

bignum::~bignum() {
    if(ptrlgnr)
        delete[]ptrlgnr;
    // o("usuniento")
}

powodem jest funkcja

void bignum::realloc(char * old,const size_t & newsize) {
    if(!old)
        throw std::bad_alloc();
    char* newone=nullptr;
    newone=new char[newsize+1] {};
    if(newone)
        for(size_t i=0; i<newsize; i++)
            newone[i]=old[i];
    else
        throw std::bad_alloc(); // jeżeli nie udała się rezerwacja pamięci.
    delete [] old;
    old=newone;
    newone=nullptr;
    return;

1 odpowiedź

+1 głos
odpowiedź 26 stycznia przez adrian17 Mentor (351,140 p.)
wybrane 28 stycznia przez TOWaD
 
Najlepsza
Pierwsze co mi wyskakuje AddressSanitizerem to że wychodzisz poza pamięć, bo iterujesz się po `newsize` elementach, ale `old` może być mniejszy.

A po drugie, no, masz kompletnie źle kopiowanie obiektów. Operator przypisania nic nie robi, a konstruktora kopiującego w ogóle nie ma - więc pewnie kompilator stworzył domyślny, który po prostu kopiuje pola. A stąd już prosta droga do double free, bo można trywialnie i nawet przypadkiem dostać dwa obiekty wskazujące na ten char* i oba wywołają destruktory.

(btw, ten `new bignum` w operator+ też super dziwnie wygląda)
komentarz 14 lutego przez TOWaD Mądrala (6,250 p.)

W konfiguracji projektu masz checkboxy

Zrobione (niestety polski gdzieś przegapiłem opcję w instalacji), ale nic nie dodało na końcu kodu.


Patrząc na screenshota, widzę co najmniej kilka dziwnych rzeczy. -static-libasan

static-libasan  - to chyba było w poradniku nie ważne.

Problem pewnie dotyczy braku cmake (pliku?/katalogu?). Bo nie chciało mi się przyklejać kodu i dodałem plik .zip do kompilatora templates>cmake>project>przeglądaj...

Może jakoś da się, cały projekt dodać.


Trudno powiedzieć ...

STL jednak w większości funkcji używa iteratorów np transform, copy itd, nie referencji

https://en.cppreference.com/w/cpp/algorithm/transform

std::transform
 
C++
Algorithm library
 
Defined in header <algorithm>
		
	(1) 	
template< class InputIt, class OutputIt, class UnaryOperation >

OutputIt transform( InputIt first1, InputIt last1,
                    OutputIt d_first, UnaryOperation unary_op );
...

 

 

komentarz 14 lutego przez adrian17 Mentor (351,140 p.)

ale nic nie dodało na końcu kodu.

Na oko u mnie działa:

STL jednak w większości funkcji używa iteratorów np transform, copy itd, nie referencji

Bo są uniwersalnym mechanizmem iteracji. To nie znaczy że referencje do rzeczy są "strzałem w stopę", szczególnie w kodzie który ma zero związku z iteracją.

komentarz 14 lutego przez TOWaD Mądrala (6,250 p.)

t

Tak to działa i nawet błąd zgłasza głównym oknie programu.

==9052==ERROR: AddressSanitizer: heap-buffer-overflow on address

szczególnie w kodzie który ma zero związku z iteracją

Konstruktor tylko robi iterację, cała klasa w paru liniach tylko nie można by było tu zrobić operatora + i -; trzeba by było używać funkcji. A walidację dało by się zrobić w lambdach.

#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    std::string normal("123");
    std::string BigNum;
    std::transform(normal.rbegin(), normal.rend(),
                    std::back_inserter(BigNum), 
                   [](unsigned char c) { return c-'0';});
    std::transform(BigNum.rbegin(), BigNum.rend(),
                     std::ostream_iterator<short>(std::cout, " "), 
                   [](unsigned char c) { return c;});
    std::cout<<std::endl;
    return 0;
}

strzałem w stopę

Osobiste doświadczenie. Po prostu nie do końca rozumiem referencję do kontenerów STL.

Nie raz mi referencja do kontenerów krwi napsuła, a już na pewno do stringa.

komentarz 14 lutego przez TOWaD Mądrala (6,250 p.)

@adrian17, Nawet za to jeszcze nie podziękowałem. Dzięki, dawno się tyle rzeczy nie dowiedziałem i to w dyskusji to nie to samo co przeczytać. Dużo bardziej zapada w pamięć.

Podobne pytania

0 głosów
1 odpowiedź 182 wizyt
pytanie zadane 30 marca 2020 w C i C++ przez Quegon23 Nowicjusz (150 p.)
0 głosów
2 odpowiedzi 391 wizyt
pytanie zadane 16 lutego 2019 w C i C++ przez niedzwiedz89 Nowicjusz (150 p.)
+2 głosów
2 odpowiedzi 787 wizyt
pytanie zadane 3 kwietnia 2017 w C i C++ przez Evelek Nałogowiec (28,960 p.)

93,188 zapytań

142,204 odpowiedzi

322,027 komentarzy

62,515 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 2581p. - dia-Chann
  2. 2537p. - Łukasz Piwowar
  3. 2528p. - Łukasz Eckert
  4. 2514p. - CC PL
  5. 2476p. - Tomasz Bielak
  6. 2445p. - Łukasz Siedlecki
  7. 2443p. - rucin93
  8. 2418p. - Michal Drewniak
  9. 2373p. - Marcin Putra
  10. 2367p. - Adrian Wieprzkowicz
  11. 2317p. - Mikbac
  12. 2156p. - Anonim 3619784
  13. 2016p. - Michał Telesz
  14. 1733p. - rafalszastok
  15. 1628p. - Dominik Łempicki (kapitan)
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...