SIGSEGV, andere Fehler... Vielleicht durch implicit sharing?

Alles rund um die Programmierung mit Qt
Antworten
Jake2012
Beiträge: 3
Registriert: 20. August 2012 21:02

SIGSEGV, andere Fehler... Vielleicht durch implicit sharing?

Beitrag von Jake2012 »

Hallo!

Ich bekomme beim Ausführen meines Programms häufig SIGSEGV (segmentation fault), aber auch “Invalid address specified to RtlFreeHeap”, “Heap corruption detected at …” oder “(Internal error: pc 0xff in read in psymtab, but not in symtab.)”. Leider sind diese Fehler kaum reproduzierbar, treten an unterschiedlichen Stellen im Code einer Funktion sowie nach unterschiedlichen (Lauf-)zeitspannen auf. Ich poste euch einfach mal den Code, wo die Fehler auftreten:

Code: Alles auswählen

void MainWindow::Aktualisierung(void)
{
    verstrichene_wartezeit += Timer1->interval();
    ui->label_20->setText(QString("Verstrichene Wartezeit: %1 Sekunden").arg(verstrichene_wartezeit/1000));

    //Bildverarbeitung starten
    QPixmap Zwischenspeicher = this->Screenshot();
    if(!Zwischenspeicher.isNull())
    {
        //Große Vorschau darstellen
        if(ui->checkBox->isChecked())
        {
            ui->label->setPixmap(Zwischenspeicher);
        }

        //Zwischenspeicher skalieren
        Zwischenspeicher = Zwischenspeicher.copy(QRect(ui->verticalSlider->value() - ui->horizontalSlider->value()/2, ui->verticalSlider_2->value() - ui->horizontalSlider->value()/2, ui->horizontalSlider->value(), ui->horizontalSlider->value()));

        //Vorschau darstellen
        if(ui->checkBox_2->isChecked())
        {
            ui->label_3->setPixmap(Zwischenspeicher); //<--- Fehler tritt u.a. hier auf
        }

        //skalieren
        Zwischenspeicher = Zwischenspeicher.scaledToHeight(ui->spinBox->value(), Qt::FastTransformation);

        QImage Bild = Zwischenspeicher.toImage();

        if(!Bild.isNull())
        {

            Bild = Bild.convertToFormat(QImage::Format_Mono, Qt::MonoOnly);

            if(Zwischenspeicher.convertFromImage(Bild, Qt::AutoColor))
            {
                //darstellen
                if(ui->checkBox_3->isChecked())
                {
                    ui->label_5->setPixmap(Zwischenspeicher);
                }

                unsigned int whitePixels = 0;

                //Pixel analysieren
                for(int i=0; i < ui->spinBox->value(); i++)
                {
                    for(int j=0; j < ui->spinBox->value(); j++)
                    {
                        if((int)Bild.pixel(i, j) & 0xFFFFFF)
                        {
                            whitePixels++;
                        }
                    }
                }
                //Weißwert anzeigen
                ui->label_12->setText(QString("Weißwert: %1%").arg((whitePixels*100)/(ui->spinBox->value()*ui->spinBox->value())));
            }
            else
            {
                qDebug("Zwischenspeicher = 0 nach .convertFromImage()");
            }
        }
        else
        {
            qDebug("Bild = 0 nach .toImage()");
        }
    }
    else
    {
        qDebug("Zwischenspeicher = 0 nach Screenshot()");
    }
}
Hier noch dei Funktion Screenshot(), aber ich glaube an ihr liegt es nicht (die Fehler treten auch alle in Aktualisierung() (s.o.) auf):

Code: Alles auswählen

QPixmap MainWindow::Screenshot(void)
{
    HWND Fenster = FindWindow(NULL, (LPCWSTR)Fenstername.utf16());
    if(Fenster)
    {
        HDC winDC = GetDC(Fenster);
        HDC memDC = CreateCompatibleDC(winDC);
        RECT rc;
        GetClientRect(Fenster, &rc);
        HBITMAP hbitmap = CreateCompatibleBitmap(winDC, rc.right-rc.left, rc.bottom-rc.top);
        SelectObject(memDC, hbitmap);
        BitBlt(memDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top, winDC, 0, 0, SRCCOPY);
        QPixmap Pixelkarte = QPixmap::fromWinHBITMAP(hbitmap, QPixmap::NoAlpha);

        ReleaseDC(Fenster, winDC);
        DeleteDC(memDC);
        DeleteObject(hbitmap);
        return Pixelkarte;
    }
    else
    {
        return QPixmap();
    }
}
Meist treten die Fehler bei QLabel->setPixmap auf und zwar (nach meinem Verständnis des Stacks) bei der Freigabe der vorherigen Daten im Zuge der Neuzuweisung.
Der Stack sieht dann z.B. (bei "Heap block at 0BE2FCD8 modified at 0BE2FCC4 past requested size of ffffffe4" an oben markierter Stelle) so aus:

Code: Alles auswählen

    0 ntdll!DbgUiConnectToDbg                   C:\WINDOWS\system32\ntdll.dll 0 
    1 ntdll!RtlpNtMakeTemporaryKey           C:\WINDOWS\system32\ntdll.dll 0 
    2 ntdll!RtlZeroHeap                              C:\WINDOWS\system32\ntdll.dll 0 
    3 ??  0 
    4 ntdll!RtlpNtMakeTemporaryKey           C:\WINDOWS\system32\ntdll.dll 0 
    5 ntdll!RtlpNtMakeTemporaryKey           C:\WINDOWS\system32\ntdll.dll 0 
    6 ntdll!LdrFindEntryForAddress             C:\WINDOWS\system32\ntdll.dll 0 
    7 ??  0 
    8 ntdll!RtlpUnWaitCriticalSection          C:\WINDOWS\system32\ntdll.dll 0 
    9 msvcrt!free                                      C:\WINDOWS\system32\msvcrt.dll 0 
    10 ??  0 
    11 QImageData::~QImageData                                      qimage.cpp 226 
    12 QImage::~QImage                                                      qimage.cpp 1283 
    13 QRasterPixmapData::~QRasterPixmapData                  qpixmap_raster.cpp 95 
    14 QExplicitlySharedDataPointer<QPixmapData>::~QExplicitlySharedDataPointer qshareddata.h 166 
    15 QPixmap::~QPixmap                                                 qpixmap.cpp 350 
    16 QLabelPrivate::clearContents                                    qlabel.cpp 1382 
    17 QLabel::setPixmap                                                   qlabel.cpp 425 
    18 MainWindow::Aktualisierung                         mainwindow.cpp 151 
    19 MainWindow::qt_static_metacall                          moc_mainwindow.cpp 75 
    20 QMetaObject::activate                                         qobject.cpp 3547 
    21 QTimer::timeout                                               moc_qtimer.cpp 148 
    22 QTimer::timerEvent                                         qtimer.cpp 280 
    23 QObject::event                                               qobject.cpp 1157 
    24 QApplicationPrivate::notify_helper                      qapplication.cpp 4554 
    25 QApplication::notify                                              qapplication.cpp 3936 
    26 QCoreApplication::notifyInternal                           qcoreapplication.cpp 876 
    27 QCoreApplication::sendEvent                                qcoreapplication.h 231 
    28 QEventDispatcherWin32Private::sendTimerEvent                 qeventdispatcher_win.cpp 642 
    29 qt_internal_proc                                                    qeventdispatcher_win.cpp 501 
    30 USER32!GetDC                                                        C:\WINDOWS\system32\user32.dll 0 
    31 ??  0 
    32 ?? qlist.h 692 
    33 ?? qstring.h 880 
    34 qt_fast_timer_proc                                                 qeventdispatcher_win.cpp 428
Habe mich also ein bisschen mit der Speicherverwaltung Beschäftigt und bin dabei auf "Implicit sharing" von Qt gestoßen. Könnte es sein, dass sich 'Zwischenspeicher' (QPixmap) und das QPixmap vom QLabel die Daten nach setPixmap() teilen, am Ende des scope's aber die daten (weil Zwischenspeicher "abgelaufen" ist) zerstört werden und daher der Speicher der alten Daten bei dem nächsten setPixmap() nicht freigegeben werden kann?

Ich hoffe jemand kann etwas mit dieser Fehlerdarstellung anfangen und mir weiterhelfen.
Danke schonmal!
Gruß Jake2012
Troll.Soft
Beiträge: 190
Registriert: 18. Juni 2008 09:52
Wohnort: Hamburg

Re: SIGSEGV, andere Fehler... Vielleicht durch implicit shar

Beitrag von Troll.Soft »

moin,
solche Fehler treten bei mir auf, wenn ich Speicher freigebe und dann doch noch nutze. Habe gesehen, das Du eine selbstgeschriebene Screenshot-funktion nutzt. Wenn Du die Qt eigene nutzt treten womöglich schon weniger Fehler auf :)
Doku - Stichwort - Screenshot
tschüß
Troll.Soft
Jake2012
Beiträge: 3
Registriert: 20. August 2012 21:02

Re: SIGSEGV, andere Fehler... Vielleicht durch implicit shar

Beitrag von Jake2012 »

Danke für den Tipp, ich bekomme zwar leider immernoch SIGSEGV (Stack s. unten), aber das ist natürlich eine schönere Lösung einen Screenshot zu bekommen.
So habe ich das also abgewandelt:

Code: Alles auswählen

...
//Zwischenspeicher = this->Screenshot();
Zwischenspeicher = QPixmap::grabWindow((WId)FindWindow(NULL, (LPCWSTR)Fenstername.utf16()));
...
Ich kann leider nicht entziffern, was hier den Fehler auslöst, also um welches Event (scheint jedenfalls etwas mit einem Event zu tun zu haben) es sich handelt:

Code: Alles auswählen

0	ntdll!RtlpUnWaitCriticalSection	C:\WINDOWS\system32\ntdll.dll	0	
1	ntdll!RtlpNtMakeTemporaryKey	C:\WINDOWS\system32\ntdll.dll	0	
2	ntdll!LdrFindEntryForAddress	C:\WINDOWS\system32\ntdll.dll	0	
3	??		0	
4	ntdll!RtlpUnWaitCriticalSection	C:\WINDOWS\system32\ntdll.dll	0	
5	msvcrt!free	C:\WINDOWS\system32\msvcrt.dll	0	
6	??		0	
7	qFree	qmalloc.cpp	60	
8	QVectorData::free	qvector.cpp	82	
9	QVectorTypedData<QRect>::free	qvector.h	99	
10	QVector<QRect>::free	qvector.h	468	
11	QVector<QRect>::~QVector	qvector.h	124	
12	QRegionPrivate::~QRegionPrivate	qregion.cpp	1093	
13	QRegion::cleanUp	qregion.cpp	3912	
14	QRegion::operator=	qregion.cpp	3936	
15	QClipData::setClipRegion	qpaintengine_raster.cpp	4288	
16	QRasterPaintEnginePrivate::systemStateChanged	qpaintengine_raster.cpp	1066	
17	QRasterPaintEngine::begin	qpaintengine_raster.cpp	452	
18	QPainter::begin	qpainter.cpp	1881	
19	QPainter::QPainter	qpainter.cpp	1506	
20	QMainWindow::event	qmainwindow.cpp	1356	
21	QApplicationPrivate::notify_helper	qapplication.cpp	4554	
22	QApplication::notify	qapplication.cpp	4519	
23	QCoreApplication::notifyInternal	qcoreapplication.cpp	876	
24	QCoreApplication::sendSpontaneousEvent	qcoreapplication.h	234	
25	QWidgetPrivate::drawWidget	qwidget.cpp	5585	
26	QWidgetBackingStore::sync	qbackingstore.cpp	1373	
27	QWidgetPrivate::syncBackingStore	qwidget.cpp	1891	
28	QWidget::event	qwidget.cpp	8655	
29	QMainWindow::event	qmainwindow.cpp	1478	
30	QApplicationPrivate::notify_helper	qapplication.cpp	4554	
31	QApplication::notify	qapplication.cpp	4519	
32	QCoreApplication::notifyInternal	qcoreapplication.cpp	876	
33	QCoreApplication::sendEvent	qcoreapplication.h	231	
34	QCoreApplicationPrivate::sendPostedEvents	qcoreapplication.cpp	1500	
35	qt_internal_proc	qeventdispatcher_win.cpp	496	
36	USER32!GetDC	C:\WINDOWS\system32\user32.dll	0	
37	??		0	
38	??		0	
39	??		0		
Hier taucht ja auch meine "mainwindow.cpp" nicht im Stack auf, deshalb weiß ich nicht, wo ich anfangen soll nach der Fehlerquelle zu suchen! Ich bekomme aber auch immernoch den Fehler bei setPixmap()...
Jake2012
Beiträge: 3
Registriert: 20. August 2012 21:02

Re: SIGSEGV, andere Fehler... Vielleicht durch implicit shar

Beitrag von Jake2012 »

Noch ein weiterer Fehler, denn ich gerade das erste mal bekommen habe: "Heap missing last entry in committed range near b27a088
(Internal error: pc 0x327 in read in psymtab, but not in symtab.)
":

Code: Alles auswählen

0	ntdll!DbgUiConnectToDbg	C:\WINDOWS\system32\ntdll.dll	0	0x7c91120f	
1	ntdll!RtlpNtMakeTemporaryKey	C:\WINDOWS\system32\ntdll.dll	0	0x7c97ee31	
2	ntdll!LdrFindEntryForAddress	C:\WINDOWS\system32\ntdll.dll	0	0x7c95ad1d	
3	??		0	0xb27a088	
4	ntdll!RtlRealPredecessor	C:\WINDOWS\system32\ntdll.dll	0	0x7c928cb4	
5	??		0	0xb060000	
6	towlower	C:\WINDOWS\system32\ntdll.dll	0	0x7c939ba8	
7	ntdll!RtlpNtMakeTemporaryKey	C:\WINDOWS\system32\ntdll.dll	0	0x7c97fb98	
8	ntdll!LdrFindEntryForAddress	C:\WINDOWS\system32\ntdll.dll	0	0x7c95b244	
9	??		0	0xb060000	
10	ntdll!RtlpUnWaitCriticalSection	C:\WINDOWS\system32\ntdll.dll	0	0x7c929c0c	
11	msvcrt!free	C:\WINDOWS\system32\msvcrt.dll	0	0x77bfc3c9	
12	??		0	0xb060000	
13	msvcrt!free	C:\WINDOWS\system32\msvcrt.dll	0	0x77bfc3e7	
14	??	qalgorithms.h	382	0x328	
15	??		0	0x22d1e8	
16	msvcrt!malloc	C:\WINDOWS\system32\msvcrt.dll	0	0x77bfc42e	
17	operator new	new_op.cc	63	0xe34ffb	
18	QRasterPaintEngine::createState	qpaintengine_raster.cpp	685	0x7f41eb	
19	QPainter::begin	qpainter.cpp	1800	0x7832e4	
20	QPainter::QPainter	qpainter.cpp	1506	0x782330	
21	QWidgetPrivate::drawWidget	qwidget.cpp	5562	0x69f492	
22	QWidgetBackingStore::sync	qbackingstore.cpp	1373	0x837529	
23	QWidgetPrivate::syncBackingStore	qwidget.cpp	1891	0x69717e	
24	QWidget::event	qwidget.cpp	8655	0x6a70b3	
25	QMainWindow::event	qmainwindow.cpp	1478	0xa5a334	
26	QApplicationPrivate::notify_helper	qapplication.cpp	4554	0x65c020	
27	QApplication::notify	qapplication.cpp	4519	0x65bea1	
28	QCoreApplication::notifyInternal	qcoreapplication.cpp	876	0x69dd3b76	
29	QCoreApplication::sendEvent	qcoreapplication.h	231	0x69e4488c	
30	QCoreApplicationPrivate::sendPostedEvents	qcoreapplication.cpp	1500	0x69dd4a91	
31	qt_internal_proc	qeventdispatcher_win.cpp	496	0x69df9353	
32	USER32!GetDC	C:\WINDOWS\system32\user32.dll	0	0x7e368734	
33	??		0	0x37025c	
34	USER32!GetDC	C:\WINDOWS\system32\user32.dll	0	0x7e368816	
35	qt_fast_timer_proc	qeventdispatcher_win.cpp	428	0x69df90ec	
36	USER32!GetWindowLongW	C:\WINDOWS\system32\user32.dll	0	0x7e3689cd	
37	??		0		
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: SIGSEGV, andere Fehler... Vielleicht durch implicit shar

Beitrag von Christian81 »

Ohne minimal kompilierbares Beispiel werden wir wohl nicht herausfinden wo du im Speicher rumfummelst (anders gbit es solche Crashes m.E. icht). Und wenn du das nicht liefern kannst/willst - strippe dein Programm soweit ab bis der Fehler nicht mehr auftritt.
Mit Implicit sharing hat das definitiv nichts zu tun - keine Ahnung wo du das aufgeschnappt hast...

Der Kommentar 'Zwischenspeicher skalieren' ist übrigens falsch.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten