Russian Qt Forum

Программирование => С/C++ => Тема начата: blood_shadow от Октябрь 26, 2010, 00:51



Название: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 00:51
Доброго времени суток!
Возник вопрос, не могу дойти до истины. Вызывается ф-ция addNewRecord() она создает объект Day который является диалоговым окном(имеет 3 кнопки ">>" "Ok" "Cancel") результат нажатия пользователя возращается как
Код:
 i = Day->exec(); 

в самом последнем еlse вызывается обработка нажатия "Cancel", так вот вопрос почему строка
Код:
Day = 0;
следующая после удаления объекта вызывает крах программы?

Код:
void Analysis_of_accidents::addNewRecord()
{
    Day = new Day_and_person(SizeForDialogs);
    // Construct structs for Data
    DataRepository = new QStringList;

    int i;
    i = Day->exec();

    if (i) {
        if (i==1) //Ok
        {
            *DataRepository << Day->returnDay_and_personList();

            while (DataRepository->size() < (ColumnCount - 1)) *DataRepository << *emptyString;

            delete Day;
            Day = 0;

            emit StringListIsReady();
        }
        else // >>
        {
            *DataRepository << Day->returnDay_and_personList();

            addNewRecordEmployee();
        }
    }
    else { // Cancel
        delete DataRepository;
        delete Day;
        Day = 0;
        return;
    }

    return;

}


Название: Re: Обнуление указателя
Отправлено: DOOMer от Октябрь 26, 2010, 02:00
а зачем вы пытаетесь присовить нулевое значение уже удаленному указателю?


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 06:56
Код ужасный. Обнуление указателя крах вызвать не может, ошибка в другом.


Название: Re: Обнуление указателя
Отправлено: lit-uriy от Октябрь 26, 2010, 10:07
>>а зачем вы пытаетесь присовить нулевое значение уже удаленному указателю?
Указатель НЕ удалён. Удалён объект, на который указывал указатель. А обнуление указателя - хорошая практика.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 15:47
Код ужасный. Обнуление указателя крах вызвать не может, ошибка в другом.
а можно тогда поинтересоваться в чем состоит ужастность кода?
я поэкспериментировал, если закомментировать обнуление указателя, то ошибки не будет, в чем может быть дело?


Название: Re: Обнуление указателя
Отправлено: DOOMer от Октябрь 26, 2010, 16:02
Цитировать
а можно тогда поинтересоваться в чем состоит ужастность кода?
Ну вот хотя бы в этом, имхо

Код
C++ (Qt)
if (i) {
       if (i==1) //Ok

Может лучше было бы:

Код
C++ (Qt)
if ( i == QDialog::Accepted )
{
//  if select ОК
}
else
{
// if select Cancel
}


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 16:13
+1
А еще всякие *DataRepository << *emptyString; не очень красиво.

А дело где-то дальше по коду.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 16:30
Цитировать
а можно тогда поинтересоваться в чем состоит ужастность кода?
Ну вот хотя бы в этом, имхо
ну вот отредаченая версия:
Код:
        if (i==QDialog::Accepted)
        {
            *DataRepository << Conditions->returnConditionsList();

            while (DataRepository->size() < (ColumnCount - 1)) *DataRepository << *emptyString;

            delete Conditions;
            Conditions = 0;
            delete Day;
            delete Employer;

            emit StringListIsReady();
        }
        else if (i == Day_and_person::Next)
        {
            *DataRepository << Conditions->returnConditionsList();

            addNewRecordPeoples();
        }
        else {
            delete DataRepository;
            delete Conditions;
            Conditions = 0;
            delete Day;
            delete Employer;
            return;
        }

У меня три кнопки поэтому я определил перечисление Day_and_person::Next, которое равно 3, вопрос можно как-то в базовом классе QDialog определить перечисление типа QDialog::Next?


Название: Re: Обнуление указателя
Отправлено: DOOMer от Октябрь 26, 2010, 16:33
Код
C++ (Qt)
   else {
       delete DataRepository;
       delete Conditions;
       Conditions = 0;
       delete Day;
       delete Employer;
       return;
   }
А этот elsre откуда? Покажите уж полный код этой вашей падающей  функции.

IPD  а все, увидел.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 16:35
+1
А еще всякие *DataRepository << *emptyString; не очень красиво.

А дело где-то дальше по коду.

согласен указатели выглядят в этих выражениях не красиво, а как тогда поступить если мне нужно передать этот DataRepository типа QStringList дальше по программе? или лучше передавать в качестве параметра ф-ций?


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 16:36
Программа большая? Просто по кусочкам ничего толком не понятно, кроме того, что с программированием у тебя не очень. (Извини, но это так). Если есть желание, пришли мне код на мыло, а я по свободе поковыряю его в поисках ошибки, да и постараюсь поправить код до нормального состояния.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 16:44

А этот elsre откуда? Покажите уж полный код этой вашей падающей  функции.

IPD  а все, увидел.

вот полная ф-ция
Код:
void Analysis_of_accidents::addNewRecord()
{
    Day = new Day_and_person(SizeForDialogs);
    // Construct structs for Data
    DataRepository = new QStringList;

    int i;
    i = Day->exec();

    if (i==QDialog::Accepted) //Ok
        {
            *DataRepository << Day->returnDay_and_personList();

            while (DataRepository->size() < (ColumnCount - 1)) *DataRepository << *emptyString;

            delete Day;
            Day = 0;

            emit StringListIsReady();
        }
    else if (i==Day_and_person::Next) // >>
        {
            *DataRepository << Day->returnDay_and_personList();

            addNewRecordEmployee();
        }
    else { // Cancel
        delete DataRepository;
        //delete Day;
        //Day = 0;
        return;
    }

    return;

}
Короче было выяснено что падает из-за
Код:
delete Day;
впечатление будто окно раньше удаляется чем заканчивается обработчик событий


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 16:48
Программа большая? Просто по кусочкам ничего толком не понятно, кроме того, что с программированием у тебя не очень. (Извини, но это так). Если есть желание, пришли мне код на мыло, а я по свободе поковыряю его в поисках ошибки, да и постараюсь поправить код до нормального состояния.
та вот же и пытаюсь научиться  :-\
ок, вышлю на мыло
еще вопрос остался что надо делать чтобы научиться нормально программить? я имею ввиду больше практики или больше чтения или и того и другого?


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 16:49
И то, и другое. Плюс к этому читать чужие исходники.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 16:54
И то, и другое. Плюс к этому читать чужие исходники.
пасиба, особенно за чужие исходники - это то что я обычно избегал делать


Название: Re: Обнуление указателя
Отправлено: Igors от Октябрь 26, 2010, 17:01
Код ужасный.
А еще всякие *DataRepository << *emptyString; не очень красиво.
Да ох ты ж боже мой!  :) Где же те "эталоны кода" на которые мы якобы должны равняться? Это живо напоминает нашу малышь, просто с др. стороны. Ладно. мое личное мнение

1) (косметика) Переменная "i" точно не в масть - это счетчик цикла.

2) (косметика)  Когда 2 или более if - всегда надо подумать, может здесь switch получше

3) (на вкус)
Код:
while (DataRepository->size() < (ColumnCount - 1)) *DataRepository << *emptyString;

Ну как-то оно "не то". Записать в 2 строчки явно лучше. И оте опрератоы << конечно ничего но напр append (без затей) облегчило бы понимание. А еще важнее - это вероятно метод (хотя подробностей/деталей задачи я не знаю)

4) Главное - подозрительный Day. Как я понял, он член класса. Так чего он так "втихаря" создается? А вдруг он уже создан? Однозначно это должны быть методы напр CreateDay, RemoveDay

А вообще ничего "ужастного" не вижу - мой код куда более ужастен  :)
 


Название: Re: Обнуление указателя
Отправлено: lit-uriy от Октябрь 26, 2010, 18:34
QStringList динамически создавать по-моему вообще не стоит. Можно в функцию передать имеющийся список по ссылке и с ним работать:
Код
C++ (Qt)
void func(QStringList &list)
{
// что-то делаем с list
}


Название: Re: Обнуление указателя
Отправлено: Alex_cs_gsp от Октябрь 26, 2010, 20:05
 ;D Особенно комментарии полезные. Если бы мне дали в таком ошибку искать я бы послал подальше.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 20:46


ну вообщем я его переделал с учетом советов и получилось подобное:
Код:
void Analysis_of_accidents::addNewRecordConditions()
{
    Conditions = new conditions(SizeForDialogs);
    int resultCode;
    resultCode = Conditions->exec();

    switch(resultCode) {
        case QDialog::Accepted :  //  if pressed Ok
            {
                *DataRepository << Conditions->returnConditionsList();

                while (DataRepository->size() < (ColumnCount - 1))
                    *DataRepository << ("");

                delete Conditions;
                Conditions = 0;
                delete Day;
                delete Employer;

                emit StringListIsReady();
            }
            break;

        case Day_and_person::Next :  //  if pressed >>
            {
                *DataRepository << Conditions->returnConditionsList();
                addNewRecordPeoples();
            }
            break;

        case QDialog::Rejected :  //  if pressed Close
            {
                delete DataRepository;
                delete Conditions;
                Conditions = 0;
                delete Day;
                delete Employer;
                return;
            }
    }

    return;
}
Код
C++ (Qt)
 

Указатель на QStringList *DataRepository еще не нашел на что заменить, дело в том что в них храниться значения введенные в диалоговом окне и дальше этот *DataRepository используется при вызове второго диалогового окна
Код:
addNewRecordPeoples();

Познания в С++ невелики, так что прошу не винить за глупый вопрос -
вы советовали поменять
Код:
*DataRepository << ("");
на  
Код:
*DataRepository.append("");
, но компилятор выбивает ошибку
"void value not ignored as it ought to be " в этой же строке, из ассистанта я узнал что "append" возращает void a "<<" ссылку,
какая разница воид или ссылка ведь мы просто добавляем в конец пустую строку?

СОРРИ не доглядел два раза разименовал указатель


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 21:06
1. conditions на стэке создать разве нельзя?
2. DataRepository->append("");
3. delete Day; - так и нужно?


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 21:06
А вообще ничего "ужастного" не вижу - мой код куда более ужастен  :)
Ты этим хвастаешься? :o


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 21:23
1. conditions на стэке создать разве нельзя?
2. DataRepository->append("");
3. delete Day; - так и нужно?


2. Спасибо это уже понял
3. Да, тут дело в том что при нажатии на кнопку ">>" создается следуещее окно схематически цепочка Day -> Employer-> Conditions -> People (каждое из которых есть диалоговым окном), а если в данном диалоговом окне нажата кнопка "Ок" или "Закрыть" то я освобождаю память удаляя эти окна и предадущие
Код:
delete Conditions;
Conditions = 0;
delete Day;
delete Employer;

Вот общая картина:
Код:
void Analysis_of_accidents::addNewRecord()
{
    Day = new Day_and_person(SizeForDialogs);
    // Construct structs for Data
    DataRepository = new QStringList;

    int resultCode;
    resultCode = Day->exec();

    switch(resultCode) {
       
        case QDialog::Accepted : // if pressed Ok
        {
            *DataRepository << Day->returnDay_and_personList();

            while (DataRepository->size() < (ColumnCount - 1))
                DataRepository->append("");

            delete Day;
            Day = 0;

            emit StringListIsReady();
        }
            break;

        case Day_and_person::Next :  // if pressed >>
        {
            *DataRepository << Day->returnDay_and_personList();
            addNewRecordEmployee();
        }
            break;

        case QDialog::Rejected : // if pressed Close
        {
            delete DataRepository;
            //delete Day;
            //Day = 0; ???
            return;
        }
    }

    return;
}

void Analysis_of_accidents::addNewRecordEmployee()
{
    Employer = new employee(SizeForDialogs);
    int resultCode;
    resultCode = Employer->exec();

    switch(resultCode) {
       
        case QDialog::Accepted :  //  if pressed Ok
            {
                *DataRepository << Employer->returnEmployeesList();

                while (DataRepository->size() < (ColumnCount - 1))
                    DataRepository->append("");

                delete Employer;
                Employer = 0;
                delete Day;

                emit StringListIsReady();
            }
                break;

        case Day_and_person::Next :  //  if pressed >>
            {
                *DataRepository << Employer->returnEmployeesList();
                addNewRecordConditions();
            }
                break;

        case QDialog::Rejected :  //  if pressed Close
            {
                delete DataRepository;
                delete Employer;
                Employer = 0;
                delete Day;
                return;
            }
    }

    return;
}

void Analysis_of_accidents::addNewRecordConditions()
{
    Conditions = new conditions(SizeForDialogs);
    int resultCode;
    resultCode = Conditions->exec();

    switch(resultCode) {
       
        case QDialog::Accepted :  //  if pressed Ok
            {
                *DataRepository << Conditions->returnConditionsList();

                while (DataRepository->size() < (ColumnCount - 1))
                    DataRepository->append("");

                delete Conditions;
                Conditions = 0;
                delete Day;
                delete Employer;

                emit StringListIsReady();
            }
            break;

        case Day_and_person::Next :  //  if pressed >>
            {
                *DataRepository << Conditions->returnConditionsList();
                addNewRecordPeoples();
            }
            break;

        case QDialog::Rejected :  //  if pressed Close
            {
                delete DataRepository;
                delete Conditions;
                Conditions = 0;
                delete Day;
                delete Employer;
                return;
            }
    }

    return;
}

void Analysis_of_accidents::addNewRecordPeoples()
{
    Peoples = new peoples(SizeForDialogs);
    int resultCode;
    resultCode = Peoples->exec();

    switch(resultCode)
    {
        case QDialog::Accepted :  //  if pressed Ok
            {
                *DataRepository << Peoples->returnPeoplesList();
                emit StringListIsReady();
            }
        break;

        case QDialog::Rejected :  //  if pressed Close
            {
                delete DataRepository;
            }
    }

    delete Day;
    delete Employer;
    delete Conditions;
    delete Peoples;

    return;
}

1. вопрос не понял


Название: Re: Обнуление указателя
Отправлено: Пантер от Октябрь 26, 2010, 21:25
Day = new Day_and_person(SizeForDialogs); - в куче
Day_and_person Day (SizeForDialogs); - в стэке (удалять не нужно)

Тебе нужно пересмотреть архитектуру приложения.


Название: Re: Обнуление указателя
Отправлено: blood_shadow от Октябрь 26, 2010, 21:34
Day = new Day_and_person(SizeForDialogs); - в куче
Day_and_person Day (SizeForDialogs); - в стэке (удалять не нужно)

Тебе нужно пересмотреть архитектуру приложения.


а да, но это сделано умышлено - в недалеком будущем планирую добавить кнопку "<<" чтоб возвращаться назад, а делиты я прицепил чтобы лучше понять/почувствовать возвращение памяти


Название: Re: Обнуление указателя
Отправлено: Igors от Октябрь 26, 2010, 22:12
Вот общая картина:
Код:
void Analysis_of_accidents::addNewRecord()
{
    Day = new Day_and_person(SizeForDialogs);
    // Construct structs for Data
    DataRepository = new QStringList;
...
Не по уму. Упущено главное - за каждым членом класса надо следить, тем более за членом-указателем. Нельзя так резво его создавать "где хочу" - хотя бы потому что он уже может быть создан