Bus error: 10 Przy kopiowaniu strcpy() - nietypowe

Odpowiedz Nowy wątek
2015-02-15 16:15
0

Witam, mam nietypowy problem :) Otóż sprawa jest dość irytującą, gdyż nie chodzi tu o samo strcpy(), wtedy bym nie zakładał tego wątku.
Problem polega na tym, iż przy wywołaniu metody z klasy pochodnej ( od klasy abstrakcyjnej ) która jest zwykłym setterem, wychodzi mi info o tym, że jest problem z kopiowaniem do składowych ( Bus Error: 10 ). Zaznaczam, że składowe mają zarezerwowaną odpowiednią pamięc na stosie. I tu uwaga, to dotyczy sytuacji kiedy metoda jest wywołana na rzecz zwróconej referencji obiektu z metody wirtualnej klasy pochodnej ! Czyli np:

Parent->init(ptr).setFullName(const char, const char*)

init() tak jak wspomniałem to metoda polimorficzna. Bezpośrednie wywołanie Parent->setFullName() działa bez problemów !!!
Gdzie jest problem w takim razie ?

Metoda z klasy bazowej:
Person::virtual Person & init(void* data) = 0;

I polimorficzna z klasy pochodnej:
Soldier::Soldier & init(void* data)

Setter znajduje się oczywiście w klasie abstrakcyjnej i jest to zwykła metoda:

    void setFullName(const char* cname, const char* csurname) {
            cout << "name: " << cname << " surname: " << csurname << " sizeof: " << sizeof(name) << " / " << sizeof(surname) << endl;
            strcpy(name, cname);
            strcpy(surname, csurname);

        }

Takiej zagadki to już dawno nie miałem :( Gdzie tkwi problem ?

edytowany 1x, ostatnio: ŁF, 2015-02-17 12:21

Pozostało 580 znaków

2015-02-15 16:32
0

Na pewno name zawsze pomieści kopiowany cstring? Pokaż więcej kodu: jak tworzony jest name, jak wygląda override init, przykład użycia dla którego to działa i dla które nie.

Pozostało 580 znaków

2015-02-15 17:21
0

Tak pomieści. Zwróć uwagę, że podczas drukowania sprawdzam ile pamięci mają te składowe.
Poniżej przedstawiam 3 klasy:

struct driverData {
        char autoName[128];
        int skill;
    };

class Person {

    public:
        char name[64];
        char surname[128];

    public:
        virtual Person & init(void* data) = 0;
        virtual void print() {
            cout << "Name: " << name << endl;
            cout << "Surname: " << surname << endl;
        }

        void setFullName(const char* cname, const char* csurname) {
            cout << "name: " << cname << " surname: " << csurname << " sizeof: " << sizeof(name) << " / " << sizeof(surname) << endl;
            strcpy(name, cname);
            strcpy(surname, csurname);

        }

        virtual ~Person() {
            cout << "Destruktor klasy Person" << endl;
        }

};

class Soldier : public Person {

    private:
        enum { MAX_WEAPONS = 4 };
        char* weapons[MAX_WEAPONS];

    public:
        Soldier & init(void* data) {
            memcpy(weapons, data, MAX_WEAPONS * sizeof(char *));            
        }

        void print() {
            Person::print();
            int i = 0;
            cout << "Posiadana bron: " << endl;
            for(i = 0; i < MAX_WEAPONS; i++) {
                cout << weapons[i];
                if(i < MAX_WEAPONS - 1)
                    cout << ", ";
            }
            cout << endl;
        }

        ~Soldier() {
            cout << "Destruktor klasy Soldier" << endl;
        }
};

class Driver : public Person {

    private:
        char autoName[128];
        int skill;

    public:
        Driver & init(void* data) {
            struct driverData* tmp = (struct driverData *)data;
            strcpy(autoName, tmp->autoName);
            skill = tmp->skill;
        }

        void print() {
            Person::print();
            cout << "Auto: " << autoName << endl;
            cout << "Umiejetnosci: " << skill << endl;
        }

        ~Driver() {
            cout << "Destruktor klasy Driver" << endl;
        }
};

No i w main robimy testa:


const char* weapons[4] = {"karabinek M4", "granat reczny", "bagnet", "pistolet"};
Person* soldier = new Soldier();

// TAK NIE DZIALA !!!
soldier->init(weapons).setFullName("Franc", "Szurniety");

// TAK JEST OK:
soldier->setFullName("Wieslaw", "Zwyciezca");
edytowany 1x, ostatnio: ŁF, 2015-02-17 12:21

Pozostało 580 znaków

2015-02-15 17:29

A gdzie return w metodach init()?

Pozostało 580 znaków

2015-02-16 12:57
0

No właśnie to samo pytanie zadałem kompilatorowi ;) Wcześniej było void zmieniłem na referencję i przeoczyłem, ale jeśli nie ma zgodności typu zwracanego w deklaracji z definicją to zawsze kompilator wywalał błąd a tutaj nic, jedyna różnica, to taka, że init() jest czysto wirtualną metodą w klasie abstrakcyjnej ( Tam wiadomo nie może być definicji samej metody ). Gdybym to robił w XCode to samo IDE by zgłosiło błąd a ten kodzik pisałem w zwykłym edytorze zdając się na błędy wykazywane przez kompilator. A to standardowy kompilator: i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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