C++ Tablica dynamiczna wysypuje się przy dodawaniu stringów do tablicy.
Ostatnio zmodyfikowano 2019-11-07 17:56
greenbanzai Temat założony przez niniejszego użytkownika |
C++ Tablica dynamiczna wysypuje się przy dodawaniu stringów do tablicy. » 2019-11-06 22:48:50 Cześć! Kiedy ustawiam, że moja tablica dynamiczna ma przechowywać obiekty typu string i w pętli for dodaję kolejne elementy i przychodzi czas na utworzenie nowej tablicy o większej pojemności (u mnie w kodzie capacity) to program zgłasza wyjątek:"Zgłoszono wyjątek: naruszenie dostępu do zapisu. this->**_Myproxy** było 0xFDFDFDFD." oraz przenosi mnie linii 239 pliku xutility. Moja domyślna capacity to 10. Kiedy do tablicy dodaję np. 3 stringi to wszystko działa poprawnie. Program działa poprawnie dla charów i intów. Czy może być to spowodowane złym zwalnianiem pamięci lub jakimś wskaźnikiem wskazującym na jakąś głupotę? Czemu więc program działa dla intów i charów? Poniżej wklejam kod: #include "pch.h" #include <iostream> #include <string> #include <time.h> using namespace std;
template < typename T > class Arr { T * data; int capacity, len; public: Arr() { capacity = 10; len = 0; data = new T[ capacity ]; } ~Arr() { delete[] data; } void add( T value ) { if( capacity <= len ) { capacity = 2 * capacity; T * temp = new T[ capacity ]; for( int i = 0; i <= len; i++ ) { temp[ i ] = move( data[ i ] ); } delete[] data; data = temp; } data[ len++ ] = value; } const T retVal( const int index ) { if( index >= len ) { cout << "Nie ma elementu o takim indeksie, zwracam wartosc el. [0]: "; return this->data[ 0 ]; } else return this->data[ index ]; } void change( int index, T new_data ) { if( index > len ) { cout << "Nie ma takiego elementu" << endl; return; } data[ index ] = new_data; } void clean() { if( len == 0 ) { cout << "Tablica pusta!" << endl; return; } len = len - 1; for( int i = len; i >= 1; --i ) { data[ i ].~T(); len--; } } void getData() { cout << endl << "Akt. pojemnosc tablicy: " << capacity << endl; cout << "Liczba el. w tablicy: " << len << endl; } void delLast() { data[ len-- ].~T(); } void printArr() { for( int i = 0; i < len; i++ ) { cout << data[ i ] << " "; } } }; string randomString( int length ) { string rs; static const char chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; int size = sizeof( chars ); for( int i = 0; i < length; i++ ) { rs = rs + chars[ rand() %( size - 1 ) ]; } return rs; } int main() { Arr < string > * tab = new Arr < string >(); const int order = 7; const int n = pow( 10, order ); clock_t start = clock(); double max_time_per_element = 0.0; srand( time( 0 ) ); for( int i = 0; i < n; i++ ) { string el = randomString( 3 ); clock_t start2 = clock(); tab->add( el ); clock_t stop2 = clock(); double time_per_element =( stop2 - start2 ) / CLOCKS_PER_SEC; if( time_per_element > max_time_per_element ) { time_per_element = max_time_per_element; cout << max_time_per_element << endl; } } clock_t stop = clock(); double general_time =( stop - start ) / CLOCKS_PER_SEC; tab->getData(); cout << "Czas calej operacji to: " << general_time << endl; tab->printArr(); tab->clean(); delete tab; return 0; }
|
|
pekfos |
» 2019-11-07 00:40:47 for( int i = 0; i <= len; i++ )
|
Przekraczasz zakres tablicy. To jest błędne. |
|
greenbanzai Temat założony przez niniejszego użytkownika |
» 2019-11-07 10:02:40 Dziękuje za pomoc, racja, po poprawce program śmiga. Tak z ciekawości, dlaczego przekraczając zakres tablicy, kiedy w mojej tablicy przechowywałem inty czy chary program działał, a dla stringów się wysypywał? Po prostu ciekawi mnie powód. Co w data[ i ].~T(); jest źle? Myślałem, że po prostu dla pola data o indeksie zaczynającym się od len-1 czyli ostatniego elementu schodzę w dół usuwając ostatni element z tablicy aż nie dojdę do ostatniego elementu, gdzie zmniejszam długość o 1 i uzyskuję pustą tablicę. Jeśli się mylę to proszę o poprawienie mnie. void clean() { if( len == 0 ) { cout << "Tablica pusta!" << endl; return; } len = len - 1; for( int i = len; i >= 1; --i ) { data[ i ].~T(); len--; }
|
|
pekfos |
» 2019-11-07 17:56:39 Tak z ciekawości, dlaczego przekraczając zakres tablicy, kiedy w mojej tablicy przechowywałem inty czy chary program działał, a dla stringów się wysypywał? Po prostu ciekawi mnie powód. |
W obu przypadkach program jest błędny. Przekroczenie zakresu tablicy powoduje interpretowanie jako obiekt pamięci, która takiego obiektu nie zawiera. W przypadku int trzeba odpowiedniej architektury procesora, żeby błędna reprezentacja sama z siebie spowodowała błąd. std::string zawiera wskaźniki, a odwoływanie się do przypadkowych adresów w pamięci ma znacznie większe szanse wywołać fajerwerki. Myślałem, że po prostu dla pola data o indeksie zaczynającym się od len-1 czyli ostatniego elementu schodzę w dół usuwając ostatni element z tablicy aż nie dojdę do ostatniego elementu |
To nie jest usuwanie elementu, tylko wywołanie destruktora. Coś, po czym obiekt jest całkowicie nieużywalny, nie lepszy niż niezainicjalizowana pamięć. Przypisanie w to miejsce nowej wartości to za mało. Do tego delete automatycznie wywołuje destruktory dla wszystkich elementów tablicy, więc finalnie będziesz mieć je wywołane po kilka razy, co jest zawsze błędne. |
|
« 1 » |