Russian Qt Forum

Qt => Вопросы новичков => Тема начата: alezhe от Февраль 18, 2012, 23:16



Название: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 18, 2012, 23:16
доброго времени суток

пытаюсь динамически создать виджет из слота

Код:
void segregation::make_order(int n, double cr){
    int i,j;
//динамически создаю массивы
    QString *ar1=new QString[n];
    double  *ar2=new double[n*n];
//заполняю их значениями из данного экзэмпляра
    for (i=0; i<n; ++i){
        ar1[i]=ar_source1[i];
        for (j=0; j<n; ++j){
            ar2[i*n+j]=ar_source2[i*n+j];
        }
    }
//пытаюсь использовать указатели для создания дочернего
//экзэмпляра другого класса
    (new ordering(this, n, ar1, ar2, cr))->show();
}

результат непредсказуемый и недескретный
при одинаковом наборе действий происходят разные события:
код может выполниться успешно
или дизайнер может выдать ошибку SIGSEGV в произвольном месте, например в конструкторе создаваемого виджета на вроде бы безобидной команде типа "dist_in=new double[n*n];" или на какой-нибудь инструкции процессора или библиотечном классе

может кто-нибудь посоветовать на что следует обратить внимание
спасибо
 


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 19, 2012, 01:50
скорее всего неудаление динамических массивов ar1 и ar2 приводит к порче памяти.

а почему бы не использовать QList/QVector/QStringList (ну или STL-аналоги)?


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 19, 2012, 02:23
Цитировать
скорее всего неудаление динамических массивов ar1 и ar2 приводит к порче памяти.

ну, вообще идея в том, что бы экземпляр класса ordering и оперировал данными из созданных динамических массивов ar1 и ar2
это названия и матрица расстояний, соответственно
в виду этого также, и не использую контейнеры, так как далее алгоритмически удобнее пользоваться таким массивом

не думаю, что копирование элементов непосредственно в конструкторе ordering и последующее высвобождение памяти позволит решить проблему (разве что непосредственно из ar_source1 и ar_source2) так как остановка выполнения программы иногда происходит прямо в конструкторе ordering

я ведь правильно пониманию, ни завершение функции make_order, ни удаление этого экземпляра segregation (он не последний чайлд QAplication) не должно повлиять на доступность к динамическим массивам ar1 и ar2?


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 19, 2012, 02:54
не думаю, что копирование элементов непосредственно в конструкторе ordering и последующее высвобождение памяти позволит решить проблему (разве что непосредственно из ar_source1 и ar_source2) так как остановка выполнения программы иногда происходит прямо в конструкторе ordering
а, так эти динамические массивы просто присваиваются (без выделения памяти) каким-то другим в конструкторе ordering, и когда-то потом в ordering (например в деструкторе) удаляются? это, вообще говоря, очень неинтуитивное поведение.
я ведь правильно пониманию, ни завершение функции make_order, ни удаление этого экземпляра segregation (он не последний чайлд QAplication) не должно повлиять на доступность к динамическим массивам ar1 и ar2?
по идее да
Цитировать
(new ordering(this, n, ar1, ar2, cr))->show();
эта запись тоже далеко не из лучших, хотя вроде как проблем не должна создавать. попробуй создавать и показывать виджет через переменную - вдруг поможет.

ну и ещё вариант - память портится где-то раньше :)


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 19, 2012, 03:15
Цитировать
память портится где-то раньше
вот я и думаю, где же я мог так напортить  ???
что аж новый объект создается лишь в 1/3 случаев  :-[

и ordering я пробовал создавать с указателями (как с членами класс segregation, так и объявленным внутри метода, приведенный вариант - упрощенный)

может компилятор сменить?

все работает нормально, если создавать ordering в конструкторе segregation, но при этом нужно пересылать полный набор данных, а основная идея, как раз в их выборочности

Цитировать
попробуй создавать и показывать виджет через переменную
и еще про переменные-указатели:
ошибка также иногда возникала на стадии
p_ordering->show();


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 19, 2012, 03:42
вряд ли дело в компиляторе ;)

покажи конструктор ordering


Название: Re: ошибки при динамическом создании виджета
Отправлено: alexandros от Февраль 19, 2012, 12:35
Попробуй QStringList


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 19, 2012, 13:25
конструктор ordering
он немного отличается по параметрам от приведенного в первом сообщении,
в первом сообщении я немного изменил прототип, для простоты восприятия

Код:
ordering::ordering(QWidget *parent, int i_n, QString *i_genes, double i_crit,
                   double *i_dist_in, double *i_recomb_in) :
    QWidget(parent,Qt::Window)
{
    //присваиваю членам класс входящие значения
    n=n_e=i_n;
    m_crit=crit=i_crit;
    genes=i_genes;
    dist_in=i_dist_in;
    recomb_in=i_recomb_in;
    //создаю новые массивы для промежуточных и итоговых расчетов
    exist=new bool[n];
        for (int i=0; i<n; ++i){exist[i]=true;};
    tree=new bool[n*n];
    conn_in=new bool[n*n];
    ways_in=new double[n*n];
    center=new double[n];
    genes_sr=new QString[n];
    dist_sr=new double[n*n];
    recomb_sr=new double;
    conn_sr=new bool[n*n];
    ways_sr=new double[n*n];
    dist_md=new double[n*n];
    msp_sr=new double[n*n];
    coord=new double[n*n];
    //методы класса осуществляют расчеты
    definecenter();
    cent_ch(-1);
    //создание элементов для компоновки и отображения элементов
    panel_layout=new QHBoxLayout(this);
    right_layout=new QVBoxLayout(this);
    table_layout=new QVBoxLayout(this);
    p_box=new points_box(this,n,genes);
    r_box=new relation_box(this, m_crit);
    graph=new d2_graf(this, n, &n_e, genes_sr, coord, conn_sr, tree);
    //компоновка элементов
    setLayout(panel_layout);
    panel_layout->addWidget(p_box);
    panel_layout->addLayout(right_layout);
    panel_layout->addLayout(table_layout);
    right_layout->addWidget(r_box);
    right_layout->addWidget(graph);
    //
    connect(p_box, SIGNAL(point_selection(int)), this, SLOT(cent_ch(int)));
    connect(p_box, SIGNAL(point_enabling(bool*)), this, SLOT(poin_ch(bool*)));
    connect(this, SIGNAL(point_en_back(bool*)), p_box, SLOT(points_depend(bool*)));

    //отображение промежуточных результатов
    //здесь table получает значение члена класса ordering (адрес массива)
    //его размеры и отображает содержимое
    t0=new table(this, n, n, dist_sr);
    table_layout->addWidget(t0);
    t1=new table(this, n, n, ways_sr);
    table_layout->addWidget(t1);
    t3=new table(this, n, n, conn_sr);
    table_layout->addWidget(t3);
    t2=new table(this, n, n, coord);
    table_layout->addWidget(t2);
    t5=new table(this, 1, n, center);
    table_layout->addWidget(t5);
    t6=new table(this, n, n, tree);
    table_layout->addWidget(t6);
}


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 19, 2012, 13:47
Попробуй QStringList

QStringList - для передачи массива QString-ов??
не помогло


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 19, 2012, 14:57
больше одного лэйаута не может принадлежать одному и тому же виджету (но вряд ли падает из-за этого), так что
Код
C++ (Qt)
   right_layout=new QVBoxLayout(this);
   table_layout=new QVBoxLayout(this);
замени на
Код
C++ (Qt)
   right_layout=new QVBoxLayout;
   table_layout=new QVBoxLayout;
и строчка setLayout(panel_layout) не нужна, т.к. ты panel_layout'у уже задал родителя (это не ошибка, а просто лишняя команда).

конструктор вроде выглядит нормально. можешь выложить весь проект?


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 19, 2012, 15:32
больше одного лэйаута не может принадлежать одному и тому же виджету

спасибо, я это всегда подозревал, так как одно время были проблемы с памятью при уничтожении объектов, сделанных таким образом ))
теперь буду делать правильно

прикладываю файл с проектом
там же небольшое пояснение в файле description.txt


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 19, 2012, 17:15
а ты каким компилятором собираешь? студийный компилятор не разрешает выражение вида 0.0/0 и pow(int,int) (первое решается через std::numeric_limits<double>::quiet_NaN(), второе - через static_cast). есть ещё предупреждение о двух "одинаковых" конструкторах table - конструкторы не могут отличаться только типом параметра, у которого есть значение по умолчанию.

в окно вывода заглядываешь? у тебя вышеописанная ошибка с лэйатуами много где присутствует.

кириллица в исходниках и кодировка windows-1251 - это не очень хорошо.

судя по всему падает в table::paintEvent() при отрисовке текста. вполне возможно как раз из-за того, что используется неправильный конструктор по умолчанию.

убрал значения по умолчанию, закомментировал close_this() в _grouping.cpp:221 - всё заработало, только диалог поверх остаётся. если раскомментировать - падает.


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 19, 2012, 20:37
kambala, спасибо за помощь

пользуюсь QT Creator 2.3.1

из сообщений сборки у меня:
то что не все возможные варианты множества enum задействованы в switch
деление на ноль
и ошибки касающиеся используемой библиотеки alglib
про table никаких предупреждений не выдает

убрал для table значения по умолчанию, конструктор с булевым массивом, а затем и само использование table
а также исключил функцию, которая прятала диалоговое окно close_this() в grouping

(субъективно) частота успешного создания ordering возросла, но все равно программа падает

какие-то у меня принципиальные непонимания принципов Qt  :(

проблема не решена

может быть это связано с использованием сигналов? имеет смысл напрямую вызывать функцию?

и для своего развития, чем плоха кодировка windows-1251 ?


Название: Re: ошибки при динамическом создании виджета
Отправлено: Bepec от Февраль 20, 2012, 06:55
Добрый человек, а Qt у тебя версии какой?


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 20, 2012, 13:02
то что не все возможные варианты множества enum задействованы в switch
вообще-то там говорится о том, что не все control paths (не знаю как это по-русски правильно называется) возвращают значение - достаточно просто последний возврат делать не из else
убрал для table значения по умолчанию, конструктор с булевым массивом, а затем и само использование table
а также исключил функцию, которая прятала диалоговое окно close_this() в grouping

(субъективно) частота успешного создания ordering возросла, но все равно программа падает
странно, у меня всё стало работать как только я убрал скрытие диалога...
может быть это связано с использованием сигналов? имеет смысл напрямую вызывать функцию?
тоже может быть, попробуй
и для своего развития, чем плоха кодировка windows-1251 ?
плохая переносимость между системами. то ли дело UTF-8!

добавлено: кажется я понял в чём тут дело. при критическом значении  0.1 и ниже падает всегда, при больших значениях - всё стало ок. применённые фиксы:
  • убран деструктор grouping и создание элементов карты производится с родителем source
  • в segregation убрал модальность у диалога группировки с помощью group_dialog->setModal(false)
но всё равно часто падает при выходе из программы или при повторной попытке группировки


Название: Re: ошибки при динамическом создании виджета
Отправлено: alezhe от Февраль 20, 2012, 23:11
kambala, спасибо еще раз за помощь

сегодня я тоже обнаружил, что "проблемный класс" - это grouping

после моих манипуляций в гроупинг даже слот с одной командой  (new QWidget)->show()  в одном из семи случаев приводило к возникновению вечного цикла

подозреваю, что все дело в принципиально неправильном использовании QListWidget

методы void QListWidget::removeItemWidget ( QListWidgetItem * item ) и void QListWidget::addItem ( QListWidgetItem * item ) не приводили к удалению желаемого компонента из одного списка и перенесению его в другой список

в виду этого я "решал" проблему кардинально - просто создавал копию переносимого QListWidgetItem, после чего удалял простым delete оригинал и копию добавлял в другой список (заменяя в карте соответствующий адрес)

завтра буду разбираться как правильно работать со списками, но все таки хочу услышать твое мнение



Цитировать
а Qt у тебя версии какой?
а Qt 4.7.4 (32 бит)


Название: Re: ошибки при динамическом создании виджета
Отправлено: kambala от Февраль 21, 2012, 00:49
да, я тоже обратил внимание на это необычное использование QListWidgetItem, но лезть в дебри не стал. думаю тебе надо просто получше разобраться с модифицированием QListWidget.