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

Problem z dynamiczną dwuwymiarową tablicą.

Ostatnio zmodyfikowano 2013-07-20 19:54
Autor Wiadomość
Bimbol
Temat założony przez niniejszego użytkownika
Problem z dynamiczną dwuwymiarową tablicą.
» 2013-07-20 14:38:22
Witam,
mimo, że poprzedni problem został rozwiązany. To po około 30 razy bez problemowych testów, później znów program się posypał.
Tym razem nie ma
Segmentation Fault
, lecz podczas Debugowania mam inny komunikat
Program received signal SIGTRAP, Trace/breakpoint trap.
.
Dodam, że wyskakuje on nie dla wszystkich wartości. Szukałem rozwiązania na Google, jednak nic nie znalazłem.

main.cpp:
C/C++
#include "array.h"

int main()
{
    CIntArrayDouble Test( 3, 3 );
    Test.ChangeSize( 1, 10 );
   
    for( unsigned i = 0; i < Test.GetIndexSize1(); ++i )
    for( unsigned j = 0; j < Test.GetIndexSize2(); ++j )
         Test.SetValue( i, j, i + j );
   
    for( unsigned i = 0; i < Test.GetIndexSize1(); ++i )
    for( unsigned j = 0; j < Test.GetIndexSize2(); ++j )
         cout << Test.GetValue( i, j ) << endl;
   
    return 0;
}

array.h:
C/C++
#ifndef ARRAY_H_INCLUDED
#define ARRAY_H_INCLUDED

#include <iostream>
#include <memory.h>

using namespace std;

class CIntArrayDouble
{
private:
    int ** m_Table;
    unsigned m_Index1;
    unsigned m_Index2;
public:
    // Konstruktor
    CIntArrayDouble( unsigned Index1, unsigned Index2 )
        : m_Index1( Index1 )
        , m_Index2( Index2 )
    {
        m_Table = new int *[ m_Index1 ];
        for( unsigned i = 0; i < m_Index1; ++i )
             m_Table[ i ] = new int[ m_Index2 ];
       
    }
    // Dekonstruktor
    ~CIntArrayDouble()
    {
        for( unsigned i = 0; i < m_Index1; ++i )
             delete[] m_Table[ i ];
       
        delete[] m_Table;
    }
   
    // Metody
    int GetValue( unsigned Index1, unsigned Index2 )
    {
        if( Index1 > m_Index1 || Index2 > m_Index2 ) return - 1;
       
        return m_Table[ Index1 ][ Index2 ];
    }
   
    bool SetValue( unsigned Index1, unsigned Index2, int value )
    {
        if( Index1 > m_Index1 || Index2 > m_Index2 ) return false;
       
        m_Table[ Index1 ][ Index2 ] = value;
       
        return true;
    }
   
    unsigned GetIndexSize1() { return m_Index1; }
    unsigned GetIndexSize2() { return m_Index2; }
   
    void ChangeSize( unsigned Index1, unsigned Index2 )
    {
        // Tworzymy tymczasowa tablice
        int ** Array = new int *[ Index1 ];
        for( unsigned i = 0; i < Index1; ++i )
             Array[ i ] = new int[ Index2 ];
       
        // Kopiujemy zawartosc
        if( Index1 > m_Index1 )
             memcpy( Array, m_Table, sizeof( int ) * m_Index1 );
        else
             memcpy( Array, m_Table, sizeof( int ) * Index1 );
       
        m_Table = Array;
       
        m_Index1 = Index1;
        m_Index2 = Index2;
       
    }
};

#endif // ARRAY_H_INCLUDED

Na prawdę nie mam już pojęcia o co chodzi.
P-88407
pekfos
» 2013-07-20 14:45:28
C/C++
if( Index1 > m_Index1 || Index2 > m_Index2 ) return - 1;

Powinno być >=.
P-88413
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-07-20 14:51:31
Faktycznie, taki głupi i niewinny błąd.
Mimo wszystko wciąż jest ten sam problem dla niektórych wartości.
Przykładowo dla
Test.ChangeSize( 2, 5 );
 nie działa, a dla
Test.ChangeSize( 4, 2 );
 działa bez zarzutów.
P-88416
pekfos
» 2013-07-20 14:59:42
Zamiast wartości z tablicy kopiujesz wskaźniki na drugi wymiar. Dodatkowo nie zwalniasz starej tablicy.
P-88418
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-07-20 15:02:03
Czyli jak to powinno wyglądać?
Gdy zwalniam starą tablice, wyświetla błędne wartości.

Testowałem kopiowanie w funkcji main.cpp i wszystko działał w sposób, który to robiłem.
Również takie rozwiązanie znajduje się w kursie, który aktualnie przerabiam.

Hmm.. jeśli jest to źle to jak to powinno wyglądać?
P-88422
pekfos
» 2013-07-20 15:09:51
Wyjaśnię, co robisz (aktualnie i źle):
1. Alokujesz nową tablicę dwuwymiarową - tu jest jeszcze ok
2. Sprawdzasz tylko pierwszy rozmiar i kopiujesz tylko wskaźniki na stare tablice (o starym drugim rozmiarze!)
3. Aktualizujesz zmienne z rozmiarami, które mogą być niezgodne z faktycznymi rozmiarami tablic.
Do tego kopiując wskaźniki zastępujesz te, wskazujące na nowo zaalokowane bloki. W efekcie jeśli zwiększasz pierwszy rozmiar i zmieniasz drugi, to pierwsze n (stary pierwszy rozmiar) tablic będzie miało stary rozmiar, a tylko nowo dodane tablice będą miały nowy rozmiar.
P-88423
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-07-20 16:36:52
Cóż, przerobiłem nieco metodę zmiany długości tablicy.

C/C++
void ChangeSize( unsigned Index1, unsigned Index2 )
{
    // Tworzymy tymczasowa tablice
    int ** Array = new int *[ Index1 ];
    for( unsigned i = 0; i < Index1; ++i )
         Array[ i ] = new int[ Index2 ];
   
    for( unsigned i = 0; i < Index1; ++i )
    {
        memcpy( Array[ i ], m_Table[ i ], sizeof( int ) * Index2 );
        delete[] m_Table[ i ];
    }
   
    memcpy( Array, m_Table, sizeof( int ) * Index1 );
    delete[] m_Table;
   
    m_Table = Array;
   
    m_Index1 = Index1;
    m_Index2 = Index2;
   
}

Jednak występuje teraz Segmenation Faul, w Dekonstruktorze.
P-88435
pekfos
» 2013-07-20 16:44:04
Teraz gdy zwiększasz drugi rozmiar wychodzisz poza tablicę przy kopiowaniu i dalej kopiujesz stare wskaźniki..

Segmenation Faul, w Dekonstruktorze.
Fault, destruktorze.
P-88436
« 1 » 2
  Strona 1 z 2 Następna strona