Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Uszkodzenie sterty podczas zwalniania dynamicznej pamięci

Ostatnio zmodyfikowano 2018-08-17 20:59
Autor Wiadomość
Gowers
Temat założony przez niniejszego użytkownika
Uszkodzenie sterty podczas zwalniania dynamicznej pamięci
» 2018-08-17 15:54:02
Witam, robię zadania ze spoja, które ma pobierać dwa łańcuchy znaków , przekazywać je do funkcji i zwracać wskaźnik na dynamicznie zaalokowaną pamięć. Wszystko działa, ale gdy zwalniam pamięć w mainie przez
delete[] text
 wyskakuje mi komunikat "uszkodzenie sterty". Mógłby mi ktoś to wytłumaczyć? Bo nie potrafię sam tego zrozumieć. Funkcja chyba zwija stertę po zakończeniu tak? Ale z utworzoną pamięcią w niej przez operator new co się dzieje? Zostaje przecież? Domyślam się, że problem leży w tym że pamięć tworzę w funkcji, a zwalniam ją w mainie?

C/C++
#include<iostream>
#include<limits>
#include<string>
using namespace std;

char * string_merge( char *, char * );

int main()
{
    string firstText;
    string secondText;
    int t;
    int counter = 0;
    while( 1 )
    {
        cout << "Podaj ilosc: ";
        cin >> t;
        if( t > 0 && !cin.fail() )
             break;
        else if( cin.fail() )
        {
            cin.clear();
            cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        }
    }
    while( counter < t )
    {
        cout << "Podaj dwa lancuchy znakow: ";
        cin >> firstText >> secondText;
        char * a = & firstText[ 0 ];
        char * b = & secondText[ 0 ];
        char * text = string_merge( a, b ); //pobieranie wskaźnika do stworzonej pamięci w funkcji
        cout << text << endl;
        delete[] text; //zwalnianie pamięci, to powoduje uszkodzenie sterty
        counter++;
    }
   
    cout << endl;
    system( "pause" );
    return 0;
}

char * string_merge( char * a, char * b )
{
    char * text = nullptr;
    int counter = 0;
    int iteratorA = 0;
    int iteratorB = 0;
    if( strlen( a ) <= strlen( b ) )
    {
        text = new char[ 2 * strlen( a ) ]; //tworzona dynamicznie pamięć
        while( counter < 2 * strlen( a ) )
        {
            if( !( counter % 2 ) )
            {
                text[ counter ] = a[ iteratorA ]; //operacje na tej pamięci
                if( counter != 0 )
                     iteratorB++;
               
            }
            else
            {
                text[ counter ] = b[ iteratorB ];
                iteratorA++;
            }
            counter++;
        }
    }
    else
    {
        text = new char[ 2 * strlen( b ) ];
        while( counter < 2 * strlen( b ) )
        {
            if( !( counter % 2 ) )
            {
                text[ counter ] = a[ iteratorA ];
                if( counter != 0 )
                     iteratorB++;
               
            }
            else
            {
                text[ counter ] = b[ iteratorB ];
                iteratorA++;
            }
            counter++;
        }
    }
    text[ counter ] = '\0';
    return text;
}
P-172137
mateczek
» 2018-08-17 16:10:07
cout << "Podaj ilosc: ";

co to za zadanie ?? W spoju pomijasz komunikaty. Sprawdzarka dostarcza Ci strumień danych wejściowych i ty musisz odpowiedzieć strumieniem danych wyjściowych.
Nie ma tam miejsca na wymyślone komunikaty typu podaj ilość.
P-172138
Gowers
Temat założony przez niniejszego użytkownika
» 2018-08-17 16:11:44
Komunikat jest dla mnie, żebym się orientował gdzie dokładnie jestem w programie. Wszystko niepotrzebne potem kasuje. To nie jest ostateczna wersja.
To zadanie https://pl.spoj.com/problems​/PP0504B/ ale robię je na własnym kodzie.
P-172139
Monika90
» 2018-08-17 16:26:23
W twojej dynamicznie alokowanej tablicy nie ma miejsca na znak '\0'. Tak więc ta instrukcja
text[ counter ] = '\0';
 zapisuje poza tablicą.
P-172140
Gowers
Temat założony przez niniejszego użytkownika
» 2018-08-17 16:29:19
Dziękuję za pomoc
P-172141
pekfos
» 2018-08-17 16:30:30
C/C++
text[ counter ] = '\0';
Przekraczasz zakres tablicy.

Poza tym.. Nie wywołuj bez przerwy strlen(), podnosisz przez to złożoność obliczeniową do kwadratowej. I dlaczego w ogóle ręcznie zarządzasz pamięcią? Było by znacznie prościej operować na std::string, bo i tak już używasz std::string.
P-172142
mateczek
» 2018-08-17 16:31:56
C/C++
char * a = & firstText[ 0 ]; // std::string to nie tablica znaków to jest dziwne!!! i nawet nie wiem czy ma sens
const char * tablicaChar = firstText.c_str(); // jak chcesz uzyskać tablice znaków ze stringa to tak
Spoj i tak sprawdzi Ci wynik końcowy. Więc skoro robisz na stringach to możesz dokończyć na stringach
wszelkie cin.fail, cin.ignore, Do wywalenia na spoju nie możesz pomijać danych

no i autor zadania w treści umieścił funkcję main i kazał dopisać funkcję merge


P-172143
pekfos
» 2018-08-17 16:37:02
Zadanie podaje taki kod? Bad design. Na dobrą sprawę, nie trzeba w ogóle alokować żadnej pamięci
C/C++
char * text = string_merge( a, b ); //pobieranie wskaźnika do stworzonej pamięci w funkcji
cout << text << endl;
delete[] text; //zwalnianie pamięci, to powoduje uszkodzenie sterty
Po prostu wypisuj na zmianę po jednym znaku z obu napisów, skoro i tak łączysz napisy tylko po to, by je wyświetlić.
P-172144
« 1 » 2
  Strona 1 z 2 Następna strona