2014-10-01 10 views
5

내가 이해하지 못하는 초기화 목록에서 QString을 사용할 때 액세스 위반이 발생했습니다.초기화 목록의 QString에서 액세스 위반이 발생합니다. 여기서 뭐가 잘못 됐니?

다음은 문제를 재현하는 최소한의 예입니다.

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

struct Parameter 
{ 
    QString stringPar; 
}; 

class ClassA 
{ 
    QString m_string1; 

public: 
    void function(Parameter pars); 
}; 

를 ClassA의 구현 ...

// 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 
} 

및 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; 
} 

위반시 호출 스택 :

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 

뭔가가 보인다 카피 과제에 잘못 가고 싶다. n ClassA :: function() 그러나 그것이 무엇인지는 잘 모르겠습니다. 내가

function(const Parameter& pars); 

에 함수의 서명을 변경하면 이 중 충돌하지 않습니다.

의견이 있으십니까?

+2

충돌이 발생하지 않는 것처럼 보입니다 ... (Qt5.3, gcc4.8.2, kubuntu 32-bit) 충돌이 없었습니다. 컴파일러, Qt, OS 등의 버전은 무엇입니까? – HostileFork

+0

Windows 7 64 비트, 업데이트 2, Qt 5.1.1이 포함 된 Visual Studio 2013 – Knitschi

+1

'QString'을'std :: string'으로 변경하면 작동합니까? – cmannett85

답변

0

당신은 복사 생성자를 추가해야합니다 :

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

당신이를 ClassA :: 기능 (호출 할 때 임시 매개 변수 인스턴스를 값으로 인수를 전달 ++ 때문에 C의) 생성된다; 이 같은 뭔가 : 복사 생성자를 작성하지 않는 경우

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

는, 컴파일러는이 같은 기본 복사 생성자를 합성합니다

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

나는 가정, QString 포인터의 회원을 보유 추측이 이름이 있어요 ptr. 다음 pars.stringPar.ptr 및 QString ("jkjsdghdkjhgdjufgskhdbfgskzh"). stringPar.ptr은 동일한 메모리 주소를 가리 킵니다. 이 같은

전화 기능 :.

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

{QString ("jkjsdghdkjhgdjufgskhdbfgskzh")} 오브젝트가 파괴 classA.function() 반환, {QString ("jkjsdghdkjhgdjufgskhdbfgskzh")} stringPar 가리키는 다음 메모리 전에. ptr이 해제되고 및 pars.stringPar.ptr이 잘못된 메모리를 가리 킵니다. 동적으로 할당 된 메모리 클래스에 대한 복사 생성자와 할당 연산자를 선언 :

// 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. 

는 < < 효과적인 C++ >> 항목 11을 참조하십시오. 유효 C++, 2E http://debian.fmi.uni-sofia.bg/~mrpaff/Effective%20C++/EC/EI11_FR.HTM

+0

QString에는 복사 생성자와 asignment 연산자가 있습니다. 주석에서 QString 대신 std :: string을 사용하여 문제를 재현 할 수 있다고 언급했습니다. 그래서 내가 왜 매개 변수 구조체에 대한 내 자신의 복사 생성자를 작성해야 할 기본 기본 확인해야합니다 이유를 정말로 모르겠어요. "{QString ("jkjsdghdkjhgdjufgskhdbfgskzh ")} object가 classA.function() return, ... 앞에 파괴됩니다." 함수 인자의 이름없는 변수는 함수가 반환 될 때까지 계속 유지 될 것이라고 생각했지만 어쩌면 틀 렸습니다. – Knitschi