2014-10-01 12 views
5

Ich habe eine Zugriffsverletzung festgestellt, wenn ich einen QString in einer Initialisierungsliste verwende, die ich nicht verstehe.QString in der Initialisierungsliste verursacht Zugriffsverletzung. Was läuft hier falsch?

Hier ist ein minimales Beispiel, das das Problem reproduziert.

// file ClassA.h 
#pragma once 
#include <QString> 

struct Parameter 
{ 
    QString stringPar; 
}; 

class ClassA 
{ 
    QString m_string1; 

public: 
    void function(Parameter pars); 
}; 

Implementierung von KlasseA ...

// file ClassA.cpp 
#include "ClassA.h" 

void ClassA::function(Parameter pars) 
{ 
    m_string1 = pars.stringPar; // last line called in my code when the crash happens 
} 

und main.cpp

// file main.cpp 
#include "ClassA.h" 

int main() 
{ 
    ClassA classA; 

    classA.function({ QString("jkjsdghdkjhgdjufgskhdbfgskzh") }); 

    // when using this code the problem does not occur 
    //Parameter par = { QString("jkjsdghdkjhgdjufgskhdbfgskzh") }; 
    //classA.function(par); 

    return 0; 
} 

Der Call-Stack zum Zeitpunkt der Verletzung:

Qt5Cored.dll!QGenericAtomicOps<QAtomicOpsBySize<4> >::load<long>(const long & _q_value) Line 96 
Qt5Cored.dll!QBasicAtomicInteger<int>::load() Line 142 
Qt5Cored.dll!QtPrivate::RefCount::ref() Line 57 
Qt5Cored.dll!QString::operator=(const QString & other) Line 1355 
EducationalCode.exe!ClassA::function(Parameter pars) Line 6 
EducationalCode.exe!main() Line 8 

Etwas scheint mit der Kopieraufgabe falsch zu gehen i n ClassA :: function(), aber ich bin mir nicht sicher, was es ist. Wenn ich die Unterschrift Funktion

function(const Parameter& pars); 

es nicht abstürzt entweder ändern.

Haben Sie eine Idee?

+2

Sieht nicht ... abstürzen sollte und es nicht auf mich hat abstürzen (Qt5.3, gcc4.8.2, kubuntu 32-bit). Welcher Compiler, welche Version von Qt, OS usw.? – HostileFork

+0

Windows 7 64 Bit, Visual Studio 2013 mit Update 2, Qt 5.1.1 – Knitschi

+1

Wenn Sie 'QString' in' std :: string' ändern, funktioniert das? – cmannett85

Antwort

0

Sie sollten eine Kopie Konstruktor hinzu:

struct Parameter 
{ 
    QString stringPar; 
    Parameter& Parameter(const Parameter& rhs) 
    { 
     if((void*)this == (void*)&rhs) 
     { 
      return *this; 
     } 
     this->stringPar = rhs.stringPar; 
     return *this; 
    } 
}; 

Eine temporäre Parameter-Instanz erstellt, wenn Sie KlasseA aufrufen :: function() wegen C++ Argumente von Wert geht; Etwas wie folgt aus:

void ClassA::function(Parameter pars = QString("jkjsdghdkjhgdjufgskhdbfgskzh")) 
{ 
    m_string1 = pars.stringPar; // last line called in my code when the crash happens 
} 

Wenn Sie keine Kopie Konstruktor schreiben, werden Compiler einen Standard Copykonstruktor wie folgt synthetisieren:

Parameter& Parameter(const Parameter& rhs) 
    { 
     memcpy(this, &rhs, sizeof(Parameter)); 
     return *this; 
    } 

Ich denke, QString Zeiger Mitglieder hat, ist es unter der Annahme Name ist ptr. dann pars.stringPar.ptr und QString ("jkjsdghdkjhgdjufgskhdbfgskzh"). StringPar.ptr zeigt auf die gleiche Speicheradresse.

Anruffunktion wie folgt aus:

classA.function({ QString("jkjsdghdkjhgdjufgskhdbfgskzh") }); 

{QString ("jkjsdghdkjhgdjufgskhdbfgskzh")} Objekt zerstören, bevor classA.function() zurück, dann Speicher zeigte durch {QString ("jkjsdghdkjhgdjufgskhdbfgskzh")} stringPar.. ptr ist freigegeben, und pars.stringPar.ptr zeigen auf ungültigen Speicher.

// when using this code the problem does not occur 
//Parameter par1 = { QString("jkjsdghdkjhgdjufgskhdbfgskzh") }; 
//classA.function(par1) 
//par1 destroy when main() function return, thus classA.function() does not crash. 

Siehe < < Effective C++ >> Punkt 11: Eine Kopie Konstruktor deklarieren und einen Zuweisungsoperator für Klassen mit dynamisch zugewiesenen Speicher. Effective C++, 2E http://debian.fmi.uni-sofia.bg/~mrpaff/Effective%20C++/EC/EI11_FR.HTM

+0

QString verfügt über einen Copy-Constructor und einen Asignment-Operator. Ich habe in den Kommentaren erwähnt, dass das Problem reproduziert werden kann, indem std :: string anstelle von QString verwendet wird. Ich sehe also nicht wirklich, warum ich meinen eigenen Kopierkonstruktor für die Parameter struct schreiben müsste, da der Standardkonstruktor in Ordnung sein sollte. "{QString (" jkjsdghdkjhgdjufgskhdbfgskzh ")} Objekt zu zerstören, bevor classA.function() return, ...". Ich dachte, dass unbenannte Variablen in Funktionsargumenten garantiert leben werden, bis die Funktion zurückkehrt, aber vielleicht lag ich falsch. – Knitschi

Verwandte Themen