[Qt] SIGSEGV

0

Witam wszyskich serdecznie. Problem polega na tym, że ten oto kawałek kodu powoduje jakiś błąd, z którym nie wiem jak sobie poradzić. SIGSEGV, chciałbym zaznaczyć, że ten błąd nie zawsze się pojawia na dodatek też nie zawsze jest błąd w tym samym miejscu. Natomiast jeśli zaremuje kod, w którym są zapisywane ustawienia do pliku poprzez zmienna "ustawienia" (brak jej deklaracji wówczas również) to wtedy błąd się nie pojawia w ogóle. Czyli doszedłem do tego, że błąd generuje zapis ustawień do pliku, natomiast nie wiem dlaczego, może jakieś pomysły. Załączam kod generujący błąd.

Jest to slot, który jest wywoływany po wciśnięciu przycisku na formie.

void programowanie::on_komora_rozpocznij_suszenie_clicked()
{

    ui->komora_zakoncz_suszenie->setEnabled(true);
    ui->komora_rozpocznij_suszenie->setEnabled(false);

    ui->sonda1_k1->setChecked(true); //wlaczenie wszystkich wentylatorow i sond
    ui->sonda2_k1->setChecked(true);
    ui->sonda3_k1->setChecked(true);
    ui->sonda4_k1->setChecked(true);
    ui->sonda5_k1->setChecked(true);
    ui->wentylator1_k1->setChecked(true);
    ui->wentylator2_k1->setChecked(true);
    ui->wentylator3_k1->setChecked(true);
    ui->wentylator4_k1->setChecked(true);
    zapiszStanyKontrolek(m_ostatnia_suszarnia);


    nastawy_komora *tablica_nastawy = ((MainWindow*)parent())->tablica_nastawy;
    //zapiszUstawienia();
    QSettings *ustawienia = new QSettings(QApplication::applicationDirPath() + tr("\\konfiguracja.ini"), QSettings::IniFormat);

    for(int i = 0; i < 24; i++)
    {
        QString suszarnia = QString("Suszarnia") + QString("%1").arg(i+1);

        tablica_nastawy[i].suszenie_status = ustawienia->value(suszarnia + tr("/stan_pracy_komory"), 0).toInt();
        tablica_nastawy[i].jakie_suszenie = ustawienia->value(suszarnia + tr("/rodzaj_suszenia"), 0).toInt();
        tablica_nastawy[i].jakie_drewno = ustawienia->value(suszarnia + tr("/rodzaj_drewna"), 0).toInt();
        tablica_nastawy[i].wilgotnosc_koncowa = ustawienia->value(suszarnia + tr("/wilgotnosc_koncowa_drewna"), 0).toInt();
        tablica_nastawy[i].jaka_grubosc = ustawienia->value(suszarnia + tr("/grubosc_drewna"), 0).toInt();
        tablica_nastawy[i].nawilzanie_praca = ustawienia->value(suszarnia + tr("/czas_nawilzania"), 0).toInt() > 0 ? 1 : 0;
        tablica_nastawy[i].nawilzanie_przerwa = ustawienia->value(suszarnia + tr("/czas_przerwy"), 0).toInt();
        tablica_nastawy[i].obroty_prawe= ustawienia->value(suszarnia + tr("/obroty_prawe"), 0).toInt();
        tablica_nastawy[i].obroty_lewe = ustawienia->value(suszarnia + tr("/obroty_lewe", 0)).toInt();
        tablica_nastawy[i].przewietrzanie_praca = ustawienia->value(suszarnia + tr("/czas_wietrzenia"), 0).toInt();
        tablica_nastawy[i].przewietrzanie_przerwa = ustawienia->value(suszarnia + tr("/cykl_wietrzenia"), 0).toInt();
        tablica_nastawy[i].kominki_min = ustawienia->value(suszarnia + tr("/kominki_min"), 0).toInt();
        tablica_nastawy[i].kominki_max = ustawienia->value(suszarnia + tr("/kominki_max"), 0).toInt();
        tablica_nastawy[i].roznica_wilgotnosci = ustawienia->value(suszarnia + tr("/roznica_wilgotnosci"), 0).toInt();
        tablica_nastawy[i].zawor_min = ustawienia->value(suszarnia + tr("/zawor_min"), 0).toInt();
        tablica_nastawy[i].zawor_max = ustawienia->value(suszarnia + tr("/zawor_max"), 0).toInt();
        tablica_nastawy[i].roznica_temperatury = ustawienia->value(suszarnia + tr("/roznica_temperatury"), 0).toInt();
        tablica_nastawy[i].wentylatory_status = 0;
        tablica_nastawy[i].wentylatory_status |= ustawienia->value(suszarnia + tr("/wentylator1"), 0).toInt() > 0 ? 0x01 : 0;
        tablica_nastawy[i].wentylatory_status |= ustawienia->value(suszarnia + tr("/wentylator2"), 0).toInt() > 0 ? 0x02 : 0;
        tablica_nastawy[i].wentylatory_status |= ustawienia->value(suszarnia + tr("/wentylator3"), 0).toInt() > 0 ? 0x04 : 0;
        tablica_nastawy[i].wentylatory_status |= ustawienia->value(suszarnia + tr("/wentylator4"), 0).toInt() > 0 ? 0x08 : 0;
        tablica_nastawy[i].sondy_status = 0;
        tablica_nastawy[i].sondy_status |= ustawienia->value(suszarnia + tr("/sonda1"), 0).toInt() > 0 ? 0x01 : 0;
        tablica_nastawy[i].sondy_status |= ustawienia->value(suszarnia + tr("/sonda2"), 0).toInt() > 0 ? 0x02 : 0;
        tablica_nastawy[i].sondy_status |= ustawienia->value(suszarnia + tr("/sonda3"), 0).toInt() > 0 ? 0x04 : 0;
        tablica_nastawy[i].sondy_status |= ustawienia->value(suszarnia + tr("/sonda4"), 0).toInt() > 0 ? 0x08 : 0;
        tablica_nastawy[i].sondy_status |= ustawienia->value(suszarnia + tr("/sonda5"), 0).toInt() > 0 ? 0x10 : 0;
        QString nazwa = ustawienia->value(suszarnia + tr("/opis_suszarni"), tr("")).toString();
        tablica_nastawy[i].zegar1=0;
        tablica_nastawy[i].zegar1_status=0;
        tablica_nastawy[i].zegar2=0;
        tablica_nastawy[i].zegar2_status=0;


        for(int k = 0; k < 255; k++)
            tablica_nastawy[i].opis_suszarni[k] = 0;

        for(int j = 0; j < nazwa.length(); j++)
        {
            tablica_nastawy[i].opis_suszarni[j] = nazwa[j].toAscii();
        }

        //data_suszenia
        nazwa = ustawienia->value(suszarnia + tr("/data_suszenia"), tr("")).toString();

        for(int k = 0; k < 255; k++)
            tablica_nastawy[i].data_suszenia[k] = 0;

        for(int j = 0; j < nazwa.length(); j++)
        {
            tablica_nastawy[i].data_suszenia[j] = nazwa[j].toAscii();
        }
    }


    ((MainWindow*)parent())->tablica_nastawy[m_ostatnia_suszarnia-1].suszenie_status = status_ready;

    QString filename = ((MainWindow*)parent())->getFileName(m_ostatnia_suszarnia, QString::fromAscii(tablica_nastawy[m_ostatnia_suszarnia-1].opis_suszarni), false, true);

    QString suszarnia2 = tr("Suszarnia") + QString("%1").arg(m_ostatnia_suszarnia);

    ustawienia->setValue(suszarnia2 + tr("/nazwa_pliku"), filename);

    QString data = QDateTime::currentDateTime().toString(tr("yyyy-dd-MM hh:mm:ss"));
    ustawienia->setValue(suszarnia2 + tr("/data_suszenia"), data);
    ustawienia->sync();
}

Tutaj funkcja z okna głównego

QString MainWindow::getFileName(int nr_device, QString description, bool bBinary, bool bNew)
{
    QString filename;
    if(bNew)
    {
        QDate date = QDate::currentDate();
        QString sNrDevice;
        sNrDevice.sprintf("%i", nr_device);
        if(bBinary)
        {
            filename = date.toString(tr("ddMMyyyy")) + tr("_") + sNrDevice + tr("_") + description;// + ".wb";
        }
        else
        {
            filename = date.toString(tr("ddMMyyyy")) + tr("_") + sNrDevice + tr("_") + description;// + ".csv";
            //zapis nazwy pliku do struktury komory



        }
    }
    else
    {
        QSettings ustawienia(QApplication::applicationDirPath() + tr("\\konfiguracja.ini"), QSettings::IniFormat, this);
        QString suszarnia = QString("Suszarnia") + QString("%1").arg(nr_device);

        filename = ustawienia.value(suszarnia + tr("/nazwa_pliku")).toString();

    }

    return filename;
}
0

Domyślam się że system to linux?

SIGSEGV oznacza że wywaliłeś się poza przydzieloną ci pamięć.

0

Dodałem na końcu funkcji on_komora_rozpocznij_suszenie_clicked()

delete ustawienia;

Wywala się na tym delete właśnie.

0

Nie, nie, Windows XP.

0

Dziwne. Może ten obiekt został usunięty przed twoim delete i wtedy próbujesz już usuwać coś z nie swojej pamięci.

edit: nie słyszłem o sigsegv na windows, ale przeczytałem że to ma coś z przepełnieniem bufora.

0

Jak nie było delete, też sie wywalał :/

0

W takim razie wywala się na destruktorze chyba...
A to musi być dynamiczne? Nie możesz tego zadeklarować jako zmiennej lokalnej?

0

Tutaj wkleiłem wersję z dynamiczną zmienną, wcześniej miałem na lokalnej zmiennej i też się wywalał :/

0

A wywala się na destruktorze czy na zapisie do pliku w końcu?

0

Prawda, że wywala się na destruktorze.

0

Hmm...

Może spróbuj zdebugowa gdzie dokładnie w destruktorze program wylatuje w powietrze...

0

Uruchom to w debuggerze i pokaż "call stack" jaki widzisz w czasie crush'a.
Podałeś dużo kodu, ale to nie daje gwarancji, że ten właściwy, na dodatek nie bardzo się chce czytać tak napisany kod, więc jak nie podasz więcej szczegółów, to pomóc będzie trudno.

Co do daty, to popatrz na QLocale, tam można pobrać systemowy format daty i czasu, więc nie musisz się z tym bawić w tłumaczenia.

edit: zdecydowanie powinieneś nauczyć się stosować stałe! Masz mnóstwo powtarzających się wartości, a co będzie jak będziesz chciał zmienić tą wartość?

0

Wywala się w tym destrukotrze:

QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
{
    QMutexLocker locker(globalMutex());
    ConfFileHash *usedHash = usedHashFunc();
    ConfFileCache *unusedCache = unusedCacheFunc();

    for (int i = 0; i < NumConfFiles; ++i) {
        if (confFiles[i] && !confFiles[i]->ref.deref()) {
            if (confFiles[i]->size == 0) {
                delete confFiles[i].take();
            } else if (unusedCache) {
                if (usedHash)
                    usedHash->remove(confFiles[i]->name);
                QT_TRY {
                    // compute a better size?
                    //w funkcji poniżej następuje crash
                    unusedCache->insert(confFiles[i]->name, confFiles[i].data(),
                                    10 + (confFiles[i]->originalKeys.size() / 4));
                    confFiles[i].take();
                } QT_CATCH(...) {
                    // out of memory. Do not cache the file.
                    delete confFiles[i].take();
                }
            }
        }
        // prevent the ScopedPointer to deref it again.
        confFiles[i].take();
    }
}

Zagłębiając się dalej:

QHash<QString, QCache<QString, QConfFile>::Node>::findNode plik ghash.h
QHash<QString, QCache<QString, QConfFile>::Node>::find plik qhash.h
QCache<QString, QConfFile>::remove plik qcache.h
QCache<QString, QConfFile>::insert qcache.h
~QConfFileSettingsPrivate plik qsettings.cpp

0

Co jeszcze podać, żeby ktoś wpadł na pomysł o co chodzi?

0

Może dodam, że po wykonaniu funkcji on_komora_rozpocznij_suszenie_clicked() mam teraz taki komunikat od aplikacji:
Heap missing last entry in committed range near a282ad8

0

Dodam jeszcze więcej teraz za to takie błędy, już nie w destruktorze, o co z tym chodzi:

0 ntdll!DbgUiConnectToDbg C:\WINDOWS\system32\ntdll.dll 0 0x7c90120f
1 ntdll!RtlpNtMakeTemporaryKey C:\WINDOWS\system32\ntdll.dll 0 0x7c96e139
2 ntdll!LdrFindEntryForAddress C:\WINDOWS\system32\ntdll.dll 0 0x7c94ae6d
3 ?? 0 0x0a282ad8
4 ntdll!RtlRealPredecessor C:\WINDOWS\system32\ntdll.dll 0 0x7c91a3dc
5 ?? 0 0x003e0000
6 ntdll!RtlMakeSelfRelativeSD C:\WINDOWS\system32\ntdll.dll 0 0x7c928854
7 IO_UnspecifiedError C:\Qt\2010.04\qt\bin\QtGuid4.dll 0 0x013e0000
8 ?? 0 0x000015f8
9 ?? 0 0x000015e0
10 ?? 0 0x003e0000
11 ntdll!RtlpNtMakeTemporaryKey C:\WINDOWS\system32\ntdll.dll 0 0x7c96eea0
12 ntdll!LdrFindEntryForAddress C:\WINDOWS\system32\ntdll.dll 0 0x7c94b394
13 ?? 0 0x003e0000
14 ntdll!RtlDuplicateUnicodeString C:\WINDOWS\system32\ntdll.dll 0 0x7c918f21
15 msvcrt!free C:\WINDOWS\system32\msvcrt.dll 0 0x77c1c3c9
16 ?? 0 0x003e0000
17 msvcrt!free C:\WINDOWS\system32\msvcrt.dll 0 0x77c1c3e7
18 ?? 0 0x000015e0
19 ?? 0 0x00223f20
20 msvcrt!malloc C:\WINDOWS\system32\msvcrt.dll 0 0x77c1c42e
21 QClipData::initialize qpaintengine_raster.cpp 4359 0x00d3050c
22 qt_intersect_spans qpaintengine_raster.cpp 4574 0x00d30f40
23 qt_span_fill_clipped qpaintengine_raster.cpp 4646 0x00d3126a
24 drawLine_midpoint_i qpaintengine_raster.cpp 5262 0x00d32a7a
25 QRasterPaintEngine::strokePolygonCosmetic qpaintengine_raster.cpp 2273 0x00d28a6a
26 QRasterPaintEngine::drawRects qpaintengine_raster.cpp 1570 0x00d24cf7
27 QPainter::drawRects qpainter.cpp 3538 0x00cbf23e
28 QPainter::drawRect qpainter.h 617 0x012d15bf
29 qDrawShadeRect qdrawutil.cpp 226 0x00c9c020
30 QCommonStyle::drawPrimitive qcommonstyle.cpp 543 0x00e1c04b
31 QWindowsStyle::drawPrimitive qwindowsstyle.cpp 1787 0x00eeed36
32 QWindowsXPStyle::drawPrimitive qwindowsxpstyle.cpp 1281 0x00e82551
33 QCommonStyle::drawComplexControl qcommonstyle.cpp 3685 0x00e33ad0
34 QWindowsStyle::drawComplexControl qwindowsstyle.cpp 3154 0x00ef8876
35 QWindowsXPStyle::drawComplexControl qwindowsxpstyle.cpp 2443 0x00e89cff
36 QStylePainter::drawComplexControl qstylepainter.h 94 0x011e7462
37 QGroupBox::paintEvent qgroupbox.cpp 327 0x00f56cf5
38 QWidget::event qwidget.cpp 8190 0x00bed65f
39 QGroupBox::event qgroupbox.cpp 397 0x00f571c6
40 QApplicationPrivate::notify_helper qapplication.cpp 4302 0x00ba2526
41 QApplication::notify qapplication.cpp 4267 0x00ba23a6
42 QCoreApplication::notifyInternal qcoreapplication.cpp 726 0x6a1fd47a
43 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 218 0x011f9506
44 QWidgetPrivate::drawWidget qwidget.cpp 5363 0x00be648a
45 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5476 0x00be6cda
46 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
47 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
48 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
49 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
50 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
51 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
52 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
53 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
54 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
55 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
56 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
57 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
58 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
59 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
60 QWidgetPrivate::drawWidget qwidget.cpp 5412 0x00be68d5
61 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5476 0x00be6cda
62 QWidgetPrivate::paintSiblingsRecursive qwidget.cpp 5463 0x00be6b9a
63 QWidgetPrivate::drawWidget qwidget.cpp 5412 0x00be68d5
64 QWidgetBackingStore::sync qbackingstore.cpp 1292 0x00d605af
65 QWidgetPrivate::syncBackingStore qwidget.cpp 1688 0x00bddb5c
66 QWidget::event qwidget.cpp 8337 0x00bedba7
67 QApplicationPrivate::notify_helper qapplication.cpp 4302 0x00ba2526
68 QApplication::notify qapplication.cpp 4267 0x00ba23a6
69 QCoreApplication::notifyInternal qcoreapplication.cpp 726 0x6a1fd47a
70 QCoreApplication::sendEvent qcoreapplication.h 215 0x6a261bc4
71 QCoreApplicationPrivate::sendPostedEvents qcoreapplication.cpp 1367 0x6a1fe50b
72 qt_internal_proc qeventdispatcher_win.cpp 490 0x6a21f8e3
73 USER32!GetDC C:\WINDOWS\system32\user32.dll 0 0x7e368734
74 ?? 0 0x00560914
75 ?? 0 0x00000401
76 ?? 0 0x00000000

i komunikat od aplikacji:
Heap missing last entry in committed range near a282ad8

0

Problem rozwiązany. Błędem była ta linijka:
for(int k = 0; k < 255; k++)
tablica_nastawy[i].data_suszenia[k] = 0;

zmienna data_suszenia była zadeklarowana jako char[20], to powodowało naruszenie pamięci.
Za odpowiedzi i zainteresowanie,
Dziękuję.

0

Hmm...
Pytanie z ciekawości:
Wie ktoś dlaczego wywaliło sigsegv dopiero przy destruktorze obiektu ustawienia a nie podczas przypisywania poza tablicą?

0

Jasne, że wie - segfault leci dopiero przy trafieniu w niedostępną stronę pamięci, tutaj po prostu wyszedł poza bufor na stercie, mało prawdopodobne żeby za nim już nic nie było. Rozwalił struktury sterty i ew. znajdujące się dalej obiekty, posypało się przy usuwaniu, kiedy system/biblioteka standardowa próbowała skorzystać z padniętych danych.

0

Rozumiem.

Chociaż kiedyś gdy pisałem program w dev-cpp i wyszedłem o 1 index za tablicę to błąd poszedł od razu. Widzę więc że po prostu pamięć jest nieprzewidywalna.

0

Pewnie od razu poszedł bo nadpisałeś coś ważnego - np. wskaźnik leżący w pamięci zaraz za tablicą, na stosie. Dlatego np. Windows udostępnia flagi pozwalające na śledzenie sterty, zapamiętywanie callstacka dla każdej alokacji itd. bo debugowanie problemów z pamięcią jest jednym z najtrudniejszych.

1 użytkowników online, w tym zalogowanych: 0, gości: 1