Russian Qt Forum
Сентябрь 25, 2024, 18:23 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Пропадает виртуальная функция  (Прочитано 8380 раз)
dr_Begemot
Гость
« : Март 31, 2010, 11:33 »

Столкнулся с очень странной проблемой...

Есть некий базовый класс, имеющий некую виртуальную функцию. Далее создается порожденный класс с этой же функцией.

Если вызывать эту функцию в конструкторе порожденного класса, то все ок, если сразу после отработки конструктора в функции main вызвать некую функцию test() которая вызывает виртуальный метод, то программа вылетает с ошибкой Unhandled exception at 0x00000000 in Test.exe: 0xC0000005: Access violation reading location 0x00000000.

Если поставить брейк в функции тест на вызове нашего виртуального метода, то видно что он NULL.

Проект достаточно большой и выложить его не могу, но что странно, делаю классы foo и bar по той же схеме что и у меня (упрощенный вариант) - и все ок.
Более того... Базовый класс унаследован от QGLWidget, если его унаследовать от QWidget то все ок. Прототип виртуальной функции
Код:
QRect drawingRect()
В чем может быть дело?

Спасибо)

upd: в конструкторах/деструкторах виртуальные функции ведут себя как обычные
Тогда, в общем, понятно почему в конструкторе все ок, но почему при вызове из метода функция NULL? Как вообще такое может быть??? И в базовом, и в порожденном классах присутствует реализация метода drawingRect.
« Последнее редактирование: Март 31, 2010, 12:23 от dr_Begemot » Записан
niXman
Гость
« Ответ #1 : Март 31, 2010, 11:53 »

Цитировать
Прототип виртуальной функции
это ни разу не виртуальный метод Подмигивающий
Записан
dr_Begemot
Гость
« Ответ #2 : Март 31, 2010, 11:56 »

Цитировать
Прототип виртуальной функции
это ни разу не виртуальный метод Подмигивающий

Извиняюсь, но это прототип функции Подмигивающий
В базовом классе написано конечно же так:
Код:
virtual QRect drawingRect();
Записан
niXman
Гость
« Ответ #3 : Март 31, 2010, 12:08 »

Цитировать
Извиняюсь, но это прототип функции
так мы говорим про функции или методы? не сбивайте с толку!
Записан
dr_Begemot
Гость
« Ответ #4 : Март 31, 2010, 12:14 »

Цитировать
Извиняюсь, но это прототип функции
так мы говорим про функции или методы? не сбивайте с толку!

Вы любите поспорить о несущественном...
Виртуальный метод

Виртуальный метод (виртуальная функция) — в объектно-ориентированном программировании метод (функция) класса, который может быть...
Записан
cya-st
Гость
« Ответ #5 : Март 31, 2010, 12:19 »

В класе функция и метод одно и то же.
Записан
Akaiten
Гость
« Ответ #6 : Март 31, 2010, 12:31 »

Столкнулся с очень странной проблемой...
Если поставить брейк в функции тест на вызове нашего виртуального метода, то видно что он NULL.
Это как понять? Делает call по 0x0?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Март 31, 2010, 12:40 »

upd: в конструкторах/деструкторах виртуальные функции ведут себя как обычные
Тогда, в общем, понятно почему в конструкторе все ок, но почему при вызове из метода функция NULL? Как вообще такое может быть??? И в базовом, и в порожденном классах присутствует реализация метода drawingRect.
В конструкторе базового класса будет вызываться drawingRect базового класса, это нормально.
По поводу NULL ф-ции. Не знаю как Вы увидели что ф-ция NULL - у меня отладчик этого не позволяет  Улыбающийся Но если так, то

- попробуйте вызвать его явно MyClass::drawingRect()
- если это проходит - где-то Вы замочили указатель на VMT, надо разбираться где напр. вставляя drawingRect в разные места
- если все равно NULL - ну попробовать "Rebuild All" для начала. Потом закомментарить реализацию drawingRect и смотреть что скажет линкер.
Записан
dr_Begemot
Гость
« Ответ #8 : Март 31, 2010, 13:18 »

upd: в конструкторах/деструкторах виртуальные функции ведут себя как обычные
Тогда, в общем, понятно почему в конструкторе все ок, но почему при вызове из метода функция NULL? Как вообще такое может быть??? И в базовом, и в порожденном классах присутствует реализация метода drawingRect.
В конструкторе базового класса будет вызываться drawingRect базового класса, это нормально.
По поводу NULL ф-ции. Не знаю как Вы увидели что ф-ция NULL - у меня отладчик этого не позволяет  Улыбающийся Но если так, то

- попробуйте вызвать его явно MyClass::drawingRect()
- если это проходит - где-то Вы замочили указатель на VMT, надо разбираться где напр. вставляя drawingRect в разные места
- если все равно NULL - ну попробовать "Rebuild All" для начала. Потом закомментарить реализацию drawingRect и смотреть что скажет линкер.

Столкнулся с очень странной проблемой...
Если поставить брейк в функции тест на вызове нашего виртуального метода, то видно что он NULL.
Это как понять? Делает call по 0x0?

Да Грустный

Мда... если в порожденном классе drawingRect вызвать явно, то это прокатывает...
Я и rebuild all пробовал, и проект из pro-файла пересобирал...
закомментарить реализацию drawingRect - в смысле совсем закоментарить или тока реализацию??? Боюсь если тока реализацию, то вообще не скомпилиться, разве не так?
« Последнее редактирование: Март 31, 2010, 13:20 от dr_Begemot » Записан
dr_Begemot
Гость
« Ответ #9 : Март 31, 2010, 13:30 »

Если убрать функцию drawingRect() из порожденного класса, но оставить ее в базовом как виртуальную, то программа все равно вылетает на месте вызова drawingRect. Если же убрать virtual из базового класса вообще, то все ок...

Надо отметить, что если drawingRect вызывать явно, т.е писать MyClass::drawingRect то во всех случаях все корректно работает. Видимо проблема с таблицей виртуальных методов... странно только что виртуальные методы типа
Код:
virtual void mouseMoveEvent(QMouseEvent *event);
работают без проблем...

Не представляю как можно отловить такой баг Грустный
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #10 : Март 31, 2010, 15:24 »

Выложи минимальный пример, который это воспроизводит
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Апрель 01, 2010, 05:05 »

Если убрать функцию drawingRect() из порожденного класса, но оставить ее в базовом как виртуальную, то программа все равно вылетает на месте вызова drawingRect. Если же убрать virtual из базового класса вообще, то все ок...

Надо отметить, что если drawingRect вызывать явно, т.е писать MyClass::drawingRect то во всех случаях все корректно работает. Видимо проблема с таблицей виртуальных методов... странно только что виртуальные методы типа
Код:
virtual void mouseMoveEvent(QMouseEvent *event);
работают без проблем...

Не представляю как можно отловить такой баг Грустный
Если остальные виртуалы Ок (это лучше перепроверить), то дело хуже - испорчена сама VMT а не указатель на нее. Я бы объявил статический объект (чтобы конструктор вызывался до main) напр.
Код:
static MyClass test;
и в его конструкторе проверил бы drawingRect. 
Записан
dr_Begemot
Гость
« Ответ #12 : Апрель 01, 2010, 10:33 »

Выложи минимальный пример, который это воспроизводит

Проблема в том, что минимальный пример это не воспроизводит...
Код:
#include <QGLWidget>

class B;

class A : public QGLWidget{
Q_OBJECT

friend class B;
public:
A(QWidget* parrent = 0);

virtual void test();
private:
virtual QString drawingRect();
};

class B : public A{
Q_OBJECT

public:
B(QWidget* parrent = 0);

void test();
private:
QString drawingRect();
};

Код:
A::A(QWidget* parrent) : 
QGLWidget( parrent ){//QGLFormat(QGL::SampleBuffers), parent ){
}
void A::test(){
QString val = drawingRect();
}
QString A::drawingRect(){
return QString("A class");
}

B::B(QWidget* parrent) : A(parrent){
}

void B::test(){
A::test();
QString valA = A::drawingRect();
QString val = drawingRect();
}
QString B::drawingRect(){
return QString("B class");
}
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #13 : Апрель 01, 2010, 10:42 »

В таком случае, запускай свою программу под Valgrind и смотри где бьется память.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
dr_Begemot
Гость
« Ответ #14 : Апрель 01, 2010, 10:49 »

Если убрать функцию drawingRect() из порожденного класса, но оставить ее в базовом как виртуальную, то программа все равно вылетает на месте вызова drawingRect. Если же убрать virtual из базового класса вообще, то все ок...

Надо отметить, что если drawingRect вызывать явно, т.е писать MyClass::drawingRect то во всех случаях все корректно работает. Видимо проблема с таблицей виртуальных методов... странно только что виртуальные методы типа
Код:
virtual void mouseMoveEvent(QMouseEvent *event);
работают без проблем...

Не представляю как можно отловить такой баг Грустный
Если остальные виртуалы Ок (это лучше перепроверить), то дело хуже - испорчена сама VMT а не указатель на нее. Я бы объявил статический объект (чтобы конструктор вызывался до main) напр.
Код:
static MyClass test;
и в его конструкторе проверил бы drawingRect.  

Вы уверены, что так можно сделать?
Модуль оформлен в виде dll, подключаю его к тесту, и перед main пишу
Код:
static MyClass test;
так?

Если написать:
Код:
int main(int argc, char *argv[]){
    static MyClass test;
    test.drawingRect();
}
то все по прежнему, вылетает...
« Последнее редактирование: Апрель 01, 2010, 10:58 от dr_Begemot » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.056 секунд. Запросов: 23.