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

rzucanie wyjątkiem throw std::bad_array_new_length

Ostatnio zmodyfikowano 2024-03-05 13:37
Autor Wiadomość
nanoant20
Temat założony przez niniejszego użytkownika
rzucanie wyjątkiem throw std::bad_array_new_length
» 2024-03-05 11:11:03
w klasie "mySolution" staram się złapać wyjątek, gdy zostaną podane "Nieprawidłowe wymiary tablicy", ale to nie działa. Dziękuję za pomoc.
C/C++
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <random>
#include <stdexcept>  
// Dla std::bad_array_new_length

using namespace std;

class mySolution
{
private:
   
int * * tab;
   
int rowCount; //ilosc wierszy
   
int colCount; //ilosc kolumn
   
constexpr static int MIN = 7;
   
constexpr static int MAX = 777;
   
std::random_device rd;
   
std::default_random_engine eng { rd() };
   
std::uniform_int_distribution < int > distr { MIN, MAX };
public:
   
mySolution()
   
{
       
cout << "Konstruktor domyslnny bezparametrowy" << '\n';
       
this->tab = new int *[ 1 ] { nullptr };
       
       
for( unsigned int i = 0; i < 1; ++i )
       
tab[ i ] = new int[ 1 ] { 0 };
       
this->tab = nullptr;
       
this->rowCount = 0;
       
this->colCount = 0;
   
}
   
mySolution( int rows, int cols )
        :
rowCount( rows )
       
, colCount( cols )
   
{
       
try {
           
if( rowCount <= 0 || colCount <= 0 ) {
               
throw std::bad_array_new_length { }; // Rzuć wyjątek
           
}
           
           
cout << "Konstruktor domyslnny" << '\n';
           
this->tab = new int *[ rowCount ] { nullptr };
           
for( int i = 0; i < rowCount; ++i )
           
tab[ i ] = new int[ colCount ] { 0 };
       
}
       
catch( const std::bad_array_new_length & ) {
           
cerr << "Nieprawidlowe wymiary tablicy!" << endl;
           
this->tab = nullptr;
       
}
       
       
this->rowCount = rowCount;
       
this->colCount = colCount;
   
}
   
   
int size_rowCount() const
   
{
       
return this->rowCount;
   
}
   
int size_colCount() const
   
{
       
return this->colCount;
   
}
   
~mySolution()
   
{
       
//Don't forget to delete the array of pointers
       
if( tab != nullptr )
       
{
           
for( int i = 0; i < rowCount; ++i )
               
 delete[ ] tab[ i ];
           
           
delete[ ] tab;
       
}
       
cout << "~Destructor" << '\n';
   
};
   
void fill_tab()
   
{
       
for( int i = 0; i < rowCount; ++i )
       
{
           
for( int j = 0; j < colCount; ++j )
           
{
               
tab[ i ][ j ] = distr( eng );
               
//cout << "Enter [" << i << "][" << j << "] value : ";
                //cin >> tab[i][j];
           
}
           
//cout << endl;
       
}
    }
   
void display() const
   
{
       
for( int i = 0; i < rowCount; ++i )
       
{
           
cout << "Pole position " << i << setw( 4 ) << std::setfill( ' ' ) << right << "\t";
           
for( int j = 0; j < colCount; ++j )
           
{
               
cout << setw( 4 ) << std::setfill( ' ' ) << right << tab[ i ][ j ] << " ";
           
}
           
cout << "\n";
       
}
    }
}
;


auto main()->int
{
   
   
int iW { 0 }, iK { 0 }; //iW - ilosc wierszy, iK - ilosc kolumn
   
   
while(( cout << "Ile wierszy : " ) &&( cin >> iW ) &&( cout << "Ile kolumn : " ) &&( cin >> iK ) )
   
{
       
try {
           
mySolution tab( iW, iK );
           
tab.display();
           
tab.fill_tab();
           
cout << endl;
           
tab.display();
           
cout << '\n';
       
}
       
catch( const std::bad_array_new_length & ) {
           
std::cerr << "Blad tworzenia obiektu mySolution!" << std::endl;
       
}
    }
   
   
return 0;
}
P-180912
DejaVu
» 2024-03-05 11:24:28
C/C++
catch( const std::bad_array_new_length & ) {
   
W konstruktorze złapałeś wyjątek i wypisałeś komunikat, więc nie złapiesz go 'dalej'. Jeżeli chcesz go 'łapać' później to powinieneś wywalić try/catch które masz w konstruktorze.

/edit:
Jeszcze trochę 'wskazówek' odnośnie rzucania wyjątków w konstruktorze (ChatGPT):
Rzucanie wyjątków w konstruktorze klasy w C++ jest uznawane za akceptowalną i czasami niezbędną praktykę, szczególnie w sytuacjach, gdy podczas inicjalizacji obiektu napotykany jest błąd, który uniemożliwia poprawne stworzenie lub skonfigurowanie obiektu. Oto kilka kluczowych punktów, które należy wziąć pod uwagę:

1. **Zarządzanie błędami**: Rzucanie wyjątku z konstruktora jest skutecznym sposobem na sygnalizowanie, że obiekt nie został poprawnie utworzony z powodu wystąpienia pewnych problemów. Dzięki temu mechanizmowi wyjątków można przerwać proces tworzenia obiektu i poinformować wywołującego o napotkanym problemie.

2. **Zasoby i bezpieczeństwo**: Jeśli konstruktor alokuje zasoby (np. pamięć, pliki, połączenia sieciowe), które wymagają późniejszego zwolnienia lub zamknięcia, rzucenie wyjątku może być jedynym sposobem na uniknięcie wycieków zasobów w przypadku, gdy inicjalizacja nie może być dokończona pomyślnie. C++ nie wywoła destruktora obiektu, jeśli konstruktor tego obiektu nie zakończy się pomyślnie, więc odpowiedzialność za posprzątanie w takiej sytuacji leży po stronie konstruktora lub mechanizmów, które go otaczają.

3. **RAII (Resource Acquisition Is Initialization)**: Idiom RAII jest powszechnie stosowany w C++ do zarządzania zasobami, gdzie zasoby są alokowane w konstruktorze i zwalniane w destruktorze. Rzucanie wyjątku w konstruktorze jest zgodne z tym idiomem, ponieważ sygnalizuje, że zasób nie został poprawnie zdobyty i obiekt nie powinien być używany.

4. **Poprawne projektowanie i dokumentacja**: Podczas korzystania z wyjątków w konstruktorze ważne jest, aby dokładnie zaprojektować interfejsy klas i odpowiednio dokumentować zachowanie konstruktorów. Użytkownicy klasy powinni być świadomi potencjalnych wyjątków, które mogą zostać rzucone, oraz powodów, dla których mogą one wystąpić.

5. **Zarządzanie wyjątkami**: Należy odpowiednio obsługiwać wyjątki rzucone przez konstruktory, co oznacza użycie bloków `try` i `catch` tam, gdzie obiekty są tworzone. Pozwala to na eleganckie zarządzanie błędami i zapobiega niespodziewanemu zakończeniu programu.

Podsumowując, rzucanie wyjątków w konstruktorach w C++ jest praktyką, która ma swoje miejsce, szczególnie gdy chodzi o informowanie o błędach inicjalizacji i zarządzanie zasobami. Ważne jest jednak, aby robić to rozważnie i zawsze dostarczać użytkownikom klasy wystarczająco dużo informacji, aby mogli odpowiednio reagować na wyjątki.
P-180913
nanoant20
Temat założony przez niniejszego użytkownika
» 2024-03-05 13:31:10
@DejaVu zrobiłem tak jak zasugerowałeś,
Jeżeli chcesz go 'łapać' później to powinieneś wywalić try/catch które masz w konstruktorze.
ale teraz mam problem gdy, user wprowadzi wartość 0 (słownie zero). Wywala debug'er:


Debug Error:
HEAP CORRUPTION DETECTED: after Normal block (#202) at
0x0000025744DF7030.
CTR Detected that the application wrote to memory after andof heap buffer.

aktualny listing na którym to się dzieje
C/C++
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <random>
#include <stdexcept>  
// Dla std::bad_array_new_length

using namespace std;

class mySolution
{
private:
   
int * * tab;
   
int rowCount; //ilosc wierszy
   
int colCount; //ilosc kolumn
   
constexpr static int MIN = 7;
   
constexpr static int MAX = 777;
   
std::random_device rd;
   
std::default_random_engine eng { rd() };
   
std::uniform_int_distribution < int > distr { MIN, MAX };
public:
   
   
mySolution()
   
{
       
cout << "Konstruktor domyslnny bezparametrowy" << '\n';
       
this->tab = new int *[ 1 ] { nullptr };
       
       
for( unsigned int i = 0; i < 1; ++i )
       
tab[ i ] = new int[ 1 ] { 0 };
       
this->tab = nullptr;
       
this->rowCount = 0;
       
this->colCount = 0;
   
}
   
   
mySolution( int rows, int cols )
        :
rowCount( rows )
       
, colCount( cols )
   
{
       
       
if( rowCount <= 0 || colCount <= 0 ) {
           
cerr << "Nieprawidlowe wymiary tablicy!" << endl;
           
this->tab = nullptr;
       
}
       
       
cout << "Konstruktor domyslnny" << '\n';
       
this->tab = new int *[ rowCount ] { nullptr };
       
for( int i = 0; i < rowCount; ++i )
       
tab[ i ] = new int[ colCount ] { 0 };
       
       
this->rowCount = rowCount;
       
this->colCount = colCount;
   
}
   
   
int size_rowCount() const
   
{
       
return this->rowCount;
   
}
   
int size_colCount() const
   
{
       
return this->colCount;
   
}
   
~mySolution()
   
{
       
//Don't forget to delete the array of pointers
       
if( tab != nullptr )
       
{
           
for( int i = 0; i < rowCount; ++i )
               
 delete[ ] tab[ i ];
           
           
delete[ ] tab;
       
}
       
cout << "~Destructor" << '\n';
   
};
   
void fill_tab()
   
{
       
for( int i = 0; i < rowCount; ++i )
       
{
           
for( int j = 0; j < colCount; ++j )
           
{
               
tab[ i ][ j ] = distr( eng );
           
}
        }
    }
   
void display() const
   
{
       
for( int i = 0; i < rowCount; ++i )
       
{
           
cout << "Pole position " << i << setw( 4 ) << std::setfill( ' ' ) << right << "\t";
           
for( int j = 0; j < colCount; ++j )
           
{
               
cout << setw( 4 ) << std::setfill( ' ' ) << right << tab[ i ][ j ] << " ";
           
}
           
cout << "\n";
       
}
    }
}
;


auto main()->int
{
   
   
int iW { 0 }, iK { 0 }; //iW - ilosc wierszy, iK - ilosc kolumn
   
   
while(( cout << "Ile wierszy : " ) &&( cin >> iW ) &&( cout << "Ile kolumn : " ) &&( cin >> iK ) )
   
{
       
try {
           
mySolution tab( iW, iK );
           
tab.display();
           
tab.fill_tab();
           
cout << endl;
           
tab.display();
           
cout << '\n';
       
}
       
catch( const std::bad_array_new_length & ) {
           
std::cerr << "Blad tworzenia obiektu mySolution!" << std::endl;
       
}
    }
   
return 0;
}
P-180915
DejaVu
» 2024-03-05 13:33:38
Za dużo wyciąłeś kodu.
C/C++
if( rowCount <= 0 || colCount <= 0 ) {
   
throw std::bad_array_new_length { }; // Rzuć wyjątek
}
Ta linijka jest potrzebna - tj. rzucasz wyjątek, że są złe parametry, a w mainie przechwytujesz wyjątek.
P-180916
nanoant20
Temat założony przez niniejszego użytkownika
» 2024-03-05 13:37:59
@DejaVu Dziękuję. Zadziałało, tak jak należy.
P-180917
« 1 »
  Strona 1 z 1