Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.01.2012, 19:13   #1
Archet
Пользователь
 
Регистрация: 04.12.2011
Сообщений: 13
По умолчанию Функция базового класса вызывает критическую ошибку при вызове для класса-потомка

Собственно, есть вот такие штуки:

Код:
class Pack{
      protected:
              char *Msg;
              int MsgLen;
      public:
              Pack(){MsgLen=0; Msg=NULL;};
              virtual void show()=0;
              char* getM(){return Msg;}
              void setM(char *ch);
              void showM();
      };

void Pack::showM(){
     if(Msg!=NULL){cout<<Msg;}
     else{cout<<"Undefined";}
};
                

void Pack::setM(char*ch){
     if (Msg!=NULL){delete Msg;}; 
     MsgLen=strlen(ch);
     Msg=new char[MsgLen]; char *temp=ch;
     if (MsgLen!=0){ Msg=temp;}
};

class PackMail : public Pack{
     public:
             void show(){showM() }
             int get_cat(){return 1;}
};

class PackFile : public Pack{
      protected:
...
      public:
             PackFile(){};
             void show();
...
             int get_cat(){return 2;}
};
Собственно, проблема в том, что с классом PackFile нормально работают и setM(char*) и showM(), а вот при вызове их для PackMail программа падает с ошибкой.

P.S. разумеется, iostream и string.h подключены
Archet вне форума Ответить с цитированием
Старый 17.01.2012, 19:23   #2
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Текст "критической ошибки" привести не обязательно? Типа, это такой тест на внимательность - вникай в код, и догадайся что с ним не так?

А то может быть ты там просто точку с запятой забыл?

Код:
class PackMail : public Pack{
     public:
             void show(){showM() }   //<--- точка с запятой отсутствует
             int get_cat(){return 1;}
};
_Bers вне форума Ответить с цитированием
Старый 17.01.2012, 19:23   #3
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от Archet Посмотреть сообщение
Код:
void Pack::setM(char*ch){
     if (Msg!=NULL){delete Msg;}; 
     MsgLen=strlen(ch);
     Msg=new char[MsgLen]; char *temp=ch;
     if (MsgLen!=0){ Msg=temp;}
};
Я надеюсь, вот этот кусок
Код:
Msg=new char[MsgLen]; char *temp=ch;
if (MsgLen!=0){ Msg=temp;}
Это не копирование одной строки в другую?
Ведь известно, что для копирования строки, нужно использовать функцию strcpy
Код:
Msg = new char[MsgLen + 1]; // + 1 для терминирующего нуля
strcpy(Msg, ch);
netrino вне форума Ответить с цитированием
Старый 17.01.2012, 19:31   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Код:
void Pack::setM(char*ch){
     if (Msg!=NULL){delete Msg;};   //<--- ПОВЕДЕНИЕ НЕ ОПРЕДЕЛЕНО. 
//С высокой степенью вероятности - порча памяти, и крэш приложения.
//При лучших раскладах - утечка памяти.

     MsgLen=strlen(ch);  

     Msg=new char[MsgLen];   //<--- здесь выделяется блок памяти
     char *temp=ch; 
     if (MsgLen!=0){ Msg=temp;} // <--- Здесь указатель перенацеливается на внешний источник. 
             //Адрес выделенного блока теряется. Итого - утечка памяти.
             //В дальнейшем - удаление данных этого внешнего источника (вместо внутренних данных), 
             //что как минимум приведет к нарушению логики приложения
          
};
_Bers вне форума Ответить с цитированием
Старый 17.01.2012, 19:50   #5
Archet
Пользователь
 
Регистрация: 04.12.2011
Сообщений: 13
По умолчанию

Текст ошибки привести не могу, к сожалению, ибо винда просто утверждает, что работа программы была прекращена.

netrino, спасибо за strcpy. Что-то в 6 утра я забыл об этом, ночь была больно долгая. Помогло, да.

_Bers, как сделать очистку памяти от char* правильно?
Archet вне форума Ответить с цитированием
Старый 17.01.2012, 19:54   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Archet Посмотреть сообщение
Текст ошибки привести не могу, к сожалению, ибо винда просто утверждает, что работа программы была прекращена.

_Bers, как сделать очистку памяти от char* правильно?

Правило простое: как явно выделяли, так же явно освобождаем.

Если выделяли блок: ptr = new char[100500], значит удаляем блок: delete [] ptr
Если выделяли ед. объект: ptr = new char, значит удаляем ед. объект: delete ptr

Проверять ptr на нуль перед удалением не нужно, ибо удаление по нулевому указателю по стандарту правомерно и проблем не имеет.
_Bers вне форума Ответить с цитированием
Старый 17.01.2012, 19:57   #7
Archet
Пользователь
 
Регистрация: 04.12.2011
Сообщений: 13
По умолчанию

_Bers, благодарю.
Archet вне форума Ответить с цитированием
Старый 17.01.2012, 20:17   #8
Archet
Пользователь
 
Регистрация: 04.12.2011
Сообщений: 13
По умолчанию

Впрочем, раз уж открыл тему, один уточняющий вопрос.

Есть список из
Код:
struct PList{
      Pack*content;
      PList*next;};
где Pack*content - указатель на базовый абстрактный класс.
Для этого класса определена чисто виртуальная функция show(), переопределенная в каждом классе-потомке.

Верна ли следующая функция для пробегания всего списка с вызовом show() для всех элементов?

Код:
showall(Plist*head){
     PList*temp=head;
     while (temp->next!=NULL){
           temp->content->show();
           temp=temp->next;}
}
Archet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как обратиться к полям базового класса? Azartov Общие вопросы C/C++ 13 03.07.2011 20:32
Определение типа класса по переменной на объект этого класса при компиляции phomm Общие вопросы Delphi 24 08.04.2011 14:11
Ошибка при присвоении объекту производного класса объекта базового класса с исп. явного приведения типов Lanx Помощь студентам 0 06.04.2011 20:24
Использование объектов класса потомка в классе предке Invisible_ Общие вопросы C/C++ 1 05.04.2011 23:40
Ошибка при вызове метода класса coNsept Общие вопросы C/C++ 2 14.12.2010 13:09