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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Задача для специалистов (в чем ошибка)  (Прочитано 6046 раз)
andrew.k
Гость
« : Июнь 12, 2014, 15:53 »

Во вложении, очень маленький тестовый проект проект.
Его компиляция в Kubuntu 14.04 х86_64 (а так же в еще одном другом линуксе) и последующий запуск приводит к краху приложения (SIGSEGV), причем где-то в недрах Qt.

Под виндой не пробовал. Если кто сможет, отпишитесь.
Если у кого-то этот проект работает, тоже отпишитесь.

Собственно вопрос задачи, что не так с проектом?
Там один интерфейс, одна реализация и использование этого добра.
Все предельно очевидно. Но не работает.
« Последнее редактирование: Июнь 12, 2014, 15:56 от andrew.k » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Июнь 12, 2014, 16:01 »

Qt 4.8.*, mingw 4.6.2, Windows XP
Цитировать
Запускается C:\test_bad\build-arms-Desktop-Debug\debug\arms.exe...
"BaseApplication" "registered"
C:\test_bad\build-arms-Desktop-Debug\debug\arms.exe завершился с кодом 1
Записан

Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #2 : Июнь 12, 2014, 16:16 »

Ну так порядок инициализации статических объектов не определен. Улыбающийся

Перенесите это:
Код
C++ (Qt)
IApplication::IAppMap IApplication::_impl;

перед этим:
Код
C++ (Qt)
BaseApplication BaseApplication::_application;


А вообще, лучше так не мудрить.
Записан
andrew.k
Гость
« Ответ #3 : Июнь 12, 2014, 16:21 »

Ну так порядок инициализации статических объектов не определен. Улыбающийся

Перенесите это:
Код
C++ (Qt)
IApplication::IAppMap IApplication::_impl;

перед этим:
Код
C++ (Qt)
BaseApplication BaseApplication::_application;
[.quote]
А как же его перенести, если они в разных файлах находятся? При этом по идее IApplication::IAppMap IApplication::_impl; должен быть по коду и так выше, ведь он инклудится в BaseApplication

А вообще, лучше так не мудрить.
Что плохого в этом коде?
Записан
andrew.k
Гость
« Ответ #4 : Июнь 12, 2014, 16:24 »

Ну так порядок инициализации статических объектов не определен. Улыбающийся
Вот у gil9red mingw почему-то смог определить порядок инициализации, приложение работает.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #5 : Июнь 12, 2014, 16:26 »

А как же его перенести, если они в разных файлах находятся? При этом по идее IApplication::IAppMap IApplication::_impl; должен быть по коду и так выше, ведь он инклудится в BaseApplication
Просто перенесите ее в другой файл и тогда map сконструируется раньше.

Что плохого в этом коде?
Вот как раз это.
Записан
andrew.k
Гость
« Ответ #6 : Июнь 12, 2014, 16:30 »

А как же его перенести, если они в разных файлах находятся? При этом по идее IApplication::IAppMap IApplication::_impl; должен быть по коду и так выше, ведь он инклудится в BaseApplication
Просто перенесите ее в другой файл и тогда map сконструируется раньше.
В какой другой? как это повлияет на порядок инициализации? Никак.
При этом нарушится модульность. Почему часть кода IApplication должна быть в другом файле?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Июнь 12, 2014, 16:34 »

В какой другой? как это повлияет на порядок инициализации? Никак.

Сделайте так и у вас все заработает:
Код
C++ (Qt)
#include "baseapplication.h"
 
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
 
using namespace core;
 
IApplication::IAppMap IApplication::_impl;
BaseApplication BaseApplication::_application;
QCoreApplication * BaseApplication::qtapp = 0;
 
BaseApplication::BaseApplication()
   :IApplication()
{
   registerImplementation("BaseApplication", this);
}
 
int BaseApplication::run()
{
   if(qtapp)
       return 0;
   else
       return 1;
}
 
void BaseApplication::onInitialized()
{
   qDebug() << QObject::tr("BaseApplication initialized");
}
 

При этом нарушится модульность. Почему часть кода IApplication должна быть в другом файле?
Вот поэтому так, как сделали вы, делать не надо.
И тогда не понадобиться использовать такие костыли.
Записан
andrew.k
Гость
« Ответ #8 : Июнь 12, 2014, 16:38 »

В какой другой? как это повлияет на порядок инициализации? Никак.

Сделайте так и у вас все заработает:
А что делать, когда появится еще один наследник?
class AdvancedApplication : public IApplication например.
Записан
andrew.k
Гость
« Ответ #9 : Июнь 12, 2014, 16:43 »

В общем, "Диктую ответ на 1 -й вопрос 9-го билета."  Смеющийся

Действительно проблема в порядке инициализации статических объектов.

Варианты решений:
  • В файле проекта в секции SOURCES нужно перенести iapplication.cpp над baseapplication.cpp
    Это влияет на порядок инициализации и приложение будет работать.
  • Задать высокий приоритет для статического объекта _impl класса IApplication
    Таким образом IApplication::IAppMap IApplication::_impl __attribute__ ((init_priority(101)));
    Но это решение не кроссплатформенное кажется.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Июнь 12, 2014, 16:47 »

А что делать, когда появится еще один наследник?
Надеятся, что все будет хорошо (что он будет инициализироваться после конструирования map).
Так как в стандарте порядок инициализации статических объектов не определен, то получается лотерея. Один компилятор может инициализировать в одном порядке, другой в другом. Поменяете порядок линкуемых файлов - все может измениться. И т.д.
Поэтому, так лучше не делать. Или выносить такую инициализацию в отдельный файл и там прописывать в нужной последовательности.
Записан
andrew.k
Гость
« Ответ #11 : Июнь 12, 2014, 16:49 »

А что делать, когда появится еще один наследник?
Надеятся, что все будет хорошо (что он будет инициализироваться после конструирования map).
Так как в стандарте порядок инициализации статических объектов не определен, то получается лотерея. Один компилятор может инициализировать в одном порядке, другой в другом. Поменяете порядок линкуемых файлов - все может измениться. И т.д.
Поэтому, так лучше не делать. Или выносить такую инициализацию в отдельный файл и там прописывать в нужной последовательности.
А почему компилятор сам не может увидеть зависимость одного объекта от другого?
С отдельным файлом, некрасиво как-то :/

А как бы сделать аналогичную структуру без статических объектов?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Июнь 12, 2014, 17:06 »

А почему компилятор сам не может увидеть зависимость одного объекта от другого?
Компилятор компилирует единицу трансляции (один файл), про другие он даже не догадывается.

А как бы сделать аналогичную структуру без статических объектов?
Все компиляторы которые я видел, инициализировали в порядке линковки объектных файлов.
Если вы будете соблюдать порядок в котором, iapplication будет идти перед остальными наследниками, то все должно работать.

А так, почитайте Александреску про синглетоны, он подобные случаи неплохо разбирает.
Записан
andrew.k
Гость
« Ответ #13 : Июнь 12, 2014, 18:38 »

А почему компилятор сам не может увидеть зависимость одного объекта от другого?
Компилятор компилирует единицу трансляции (один файл), про другие он даже не догадывается.

А как бы сделать аналогичную структуру без статических объектов?
Все компиляторы которые я видел, инициализировали в порядке линковки объектных файлов.
Если вы будете соблюдать порядок в котором, iapplication будет идти перед остальными наследниками, то все должно работать.

А так, почитайте Александреску про синглетоны, он подобные случаи неплохо разбирает.

Спасибо за полезные ответы.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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