Problem z dynamiczna pamiecia w C stringach

0

Hej,
Natknalem sie na problem ktorego nie moge zrozumiec i rozwiazac... Otoz ponizsza funkcja find ma za zadanie zwrocic C string z danego parametru line tak dlugi dopoki nie dojdzie do znaku end. Problemem jest to ze zwracany C string oprocz wlasciwych liter zawiera tez jakies losowe znaki i nie mam pojecia jak sie ich pozbyc... Powinien zwrocic "file:" a zwraca "file:" + 2 znaki nie wiadomo skad ;/ Bylbym ogromnie wdzieczny za pomoc.

#include <iostream>
#include <string>
char * find( const char * line, int line_length, char end );

int main()
{
    std::cout << find( "file: somefile", 19, ' ' );
}

char * find( const char * line, int line_length, char end )
{
    char * old_data = new char[ line_length ];
    char * new_data = NULL;
    int counter = 0;
    while( line[ counter ] != end && counter < line_length )
    {
        old_data[ counter ] = line[ counter ];
        counter++;
    }
    new_data = new char[ counter ];
    memcpy( new_data, old_data, counter );
   
    if( counter < line_length )
         return new_data;
    else
         return "false";
   
}
0

c-string musi kończyć się zerem (kodem o wartości zero). To po pierwsze. Po drugie, po co te akcje z old_data i new_data? Po co kopiujesz do old_data zawartość, która jest w line? Wystarczy przecież, że wyliczysz wartość counter, nie musisz tu nic kopiować. Przy tworzeniu new_data musisz uwzględnić wspomniane zero na końcu.

Funkcja ma wyciek. old_data powinieneś zwolnić. Każdą pamięć, którą alokujesz na stercie powinieneś zwolnić, jeśli już nie będzie potrzebna. Także tą, którą zwróci funkcja find. I tu jest następny błąd:

...
return "false";

Tego zwolnić nie możesz, bo to nie jest pamięć sterty.

0

Dzieki za odpowiedz. A wiec przeksztalcilem funkcje tak:

char * find( const char * line, int line_length, char end )
{
    char * old_data = new char[ line_length];
    char * new_data = NULL;
    int counter = 0;
    while( line[ counter ] != end && counter < line_length )
    {
        old_data[ counter ] = line[ counter ];
        counter++;
    }
    new_data = new char[ counter];
    memcpy( new_data, old_data, counter); 
    new_data[counter] = '\0';

    if( counter < line_length )
	{
		delete [] old_data;
        return new_data;
	}
    else
	{
		delete [] old_data;
		delete [] new_data;
        return "false";
	}
   
}

Po skopiowaniu pamieci dodalem linijke new_data[counter] = '\0'; i teraz dobrze sie wysiwetla. Czy wlasnie takie jest rozwiazanie?
Nie mam tylko pojecia jak zwolnic pamiec new_data w przypaku gdy jest zwracana, bo przeciez po zwroceniu nie mam juz dostepu do new_data chyba?

1

Powinno być chyba new_data = new char[counter+1], ponieważ tablica o rozmiarze counter ma indeksy od [0] do [counter -1], a Ty odwołujesz się do indeksu [counter].

1

Czy wlasnie takie jest rozwiazanie?

Tak, choć jest tam błąd - przydzieliłeś za mało pamięci.

(...) bo przeciez po zwroceniu nie mam juz dostepu do new_data chyba?

Przecież nie usuwasz zmiennej new_data, tylko pamięć spod adresu, który ów zmienna przechowuje. Innymi słowy funkcja zwraca adres pamięci, który wewnątrz funkcji przechowuje zmienna new_data. Oczywiście cały czas masz tam błędny zapis return "false";, który będzie powodował błąd w momencie, gdy będziesz chciał zwolnić pamięć tego literału. Zamiast tego niech funkcja zwróci NULL lub cokolwiek przydzielone na stercie.

A propos bezsensu z buforami:

  1. kopiujesz z line do old_data counter znaków
  2. kopiujesz z old_data do new_data counter znaków
  3. zwracasz new_data
    jak widać punkt 2 jest zbędny, bo można przecież tak:
  4. kopiujesz z line do new_data counter znaków
  5. zwracasz new_data

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