2017-09-14 11 views
0

내가 작업하고있는이 프로그램에 메모리 누수가 있으며 커밋이 관련되어있는 한 꽤 오랜 동안 사용 해왔다. _bstr_t과 함께 = 할당 연산자를 사용하면 메모리 누수가 발생할 때마다 explanation 1explanation 2에 따라이 두 설명에 따르면_bstr_t를 사용한 메모리 누수

컨텍스트 - 데이터베이스의 빠른 SQL 쿼리를 수행하는 데 일반적으로 사용되는 데이터베이스 개체가 있습니다. 모든 방법은 결국이 방법은 데이터를이 때문에 _bstr_t의 데이터베이스를 쿼리라고 그들이 어떻게 생성 될 때마다 누출 기사에 따르면 다음과 같은 방법을

NvStatus DbUtils::ReadFromDatabase(IUnknown * poNvData, 
            const std::wstring & oConnectString, 
            const std::wstring & oSQLStatement) 
{ 
    //some checks 
    _bstr_t tbtSQLStr = oSQLStatement.c_str();//memory leak 
    _bstr_t tbtConnStr = oConnectString.c_str();//memory leak 

    //pass the _bstr_t to another method and get data from DB 
    return status; 
} 

를 사용합니다. 내 질문에 무엇이 프로그램이 블로킹 및 _bstr_t 개체 가비지 수집 강제로 방지 할 수 있습니까?

Microsoft는 사용 후 메모리를 정리하는 것이므로 데이터를 손상시키지 않고 어떻게 처리 할 수 ​​있습니까? 문자열의 깊은 복사본을 만들려고했으나 실패했습니다 ... 어떤 제안이라도 많이 받아 들여질 것입니다! 내 메모리 누수에 대한 두 개의 핫스팟은 내가 처음 게시 한이 하나 추가 조사 후

그러나 때 ...이

static bool GetValueFromVariant(VARIANT & tvInputValue, 
    std::wstring & roOutputValue) 
{ 
    _bstr_t tTemp = tvInputValue.bstrVal; 
    if(tTemp.length()>0) 
    { 
     roOutputValue = (wchar_t*) tTemp; 
    } 
    return true; 
} 

댓글이 자동으로 자신을 정리해야합니다 _bstr_t 제안 도움이되기를 바랍니다 내 Windows 서비스의 힙 크기를 디버깅 할 때 힙 크기가 계속 증가하고 디버거는이 _bstr_t 개체를 모두 사용하는 함수를 계속 가리 킵니다. 분명히 이러한 _bstr_t 정리되지 않습니다.

더 많은 컨텍스트,이 메모리 누수의 대부분은 COM 개체를 반복해서 만드는 데서 비롯된 것입니다. 그러나이 개체를 마치면 Release() 함수 호출에서 반환 된 참조 수를 확인하고, 0을 반환합니다. 따라서 COM 객체를 빌드하지 않았 음을 알고 있습니다 ...

_bstr_t의 주소에 wstring을 지정할 때 문제가 발생할 수 있습니까?

+0

'_bstr_t'는 메모리 할당과 할당 해제를 처리하는 네이티브'BSTR'을위한 스마트 래퍼입니다. 따라서 소멸자가 이것을 처리 할 것이기 때문에'_bstr_t'에서'SysFreeString'을 호출하지 않아야합니다. – Aurora

+0

그런 다음 메모리 누출이 발생했을 때 메모리 누수가 발생하면 어떻게됩니까? 내가 vs2015 디버거를 attatched 및 메모리 증가는 이러한 _bstr_t 개체를 사용하는 모든 것에서 유래 ... 왜 그들은 청소되지 않습니다? 거기에 가비지 콜렉션을 강요 할 방법이 없습니까? @ 오로라 –

+0

내 질문에 종기 같아요 - 어쨌든 새로운 호출하지 않고 bstr 사용할 수 있습니까 ??? @Aurora –

답변

0

_bstr_t 래퍼에 C 스타일 문자열을 지정하므로 예제의 첫 번째 줄에 메모리가 누출되지 않습니다. 이전에 할당 된 BSTR_bstr_t에 할당하면 상황이 달라집니다. 이 문제는 두 번째 설명에 설명되어 있습니다. 네이티브 BSTRSysAllocString를 사용하여 할당하고 (S1)에 배치하고, 여기

void foo() 
{  
    BSTR s1 = SysAllocString(L"String1"); 
    _bstr_t s2 = s1; 
} 

:

는 다음의 경우를 고려한다. 다음 줄은 s1에서 새 BSTR을 생성하며 s2에 배치됩니다. s2가 범위를 벗어나면 소멸자는 SysFreeString을 호출하여 복사본을 할당 해제합니다. 그러나 원래의 s1 변수는 손상되지 않고 유출됩니다. 따라서,

void foo() 
{ 
    BSTR s1 = SysAllocString(L"String1"); 
    _bstr_t s2(s1, false); 
} 

또는 내 의견에 표시된 바와 같이

void foo() 
{ 
    BSTR s1 = SysAllocString(L"String1");   
    _bstr_t s2; 
    s2.Attach(s1); 
} 

_bstr_t의 소멸자 SysFreeString를 호출합니다 :

이 문제를 해결하려면, 당신은 S2는 S1의 소유권을 수 있도록해야합니다 자원 할당을 돌보는 일.

일반적으로 BSTR이 캐시되므로 사용자는 메모리 할당을 즉시 보지 못할 수 있습니다. setting an environment variable에 의해 디버깅 목적으로이 동작을 비활성화 할 수 있습니다.

+0

당신은 그런 문자열에 사용 된 메모리를 할당 해제해야한다고 말했지만 절대로 ...이 프로그램은 사용 가능한 모든 메모리가 시스템에서 사용되지 않을 때까지 메모리 누수를 계속합니다. 한 번 더이 프로그램은 Windows 서비스, 그 차이가 있는지 확실하지 않습니다. 또한 vs2015 디버거에 따라 누수되는 코드 섹션을 추가했습니다. –

+0

또 다른 아이디어 : '_bstr_t'는 참조 카운트입니다. 당신은 아마도 값에 의해 당신의'_bstr_t'를 메소드 나 클래스의 인스턴스에 전달하고 있습니까? 이것은 ref-count가 아직 0에 도달하지 않았기 때문에 dtor가 트리거되지 않는 이유 일 수 있습니다. – Aurora

+0

이렇게하면 COM 개체가 만들어지고 그 개체가 만들어지기 때문에 이미 존재하는지 여부가 다시 초기화되고 다시 초기화하는 단계로 인해 위에서 설명한 메서드 호출이 발생합니다.개체의 크기가 증가하고 있지만 vs2015 디버거에 따르면 모든 변수의 크기는 동일하지만 힙 공간은 모든 스냅 샷을 증가시킵니다. –

0

첫 번째 경우에는 SysFreeString을 호출하지 마십시오. 메모리 누수가 없습니다.

_bstr_t tbtSQLStr = oSQLStatement.c_str(); 

소스 문자열의 복사본을 생성하고, tbtSQLStr이 범위를 벗어나면,이 복사본 소멸자 호출이 해제된다에

생성자

사용. 클래스 유형 래퍼를 사용하는 요점은 수동으로 SysFreeString을 호출 할 필요가 없기 때문입니다.

// .... 블록의 코드 특성에 따라이 문자열 사본을 만들 필요조차 없습니다.


두 번째 경우 (첫 번째 경우와는 별도로 두 가지 질문을 게시해야합니다), 메모리 누수가 없습니다.

tTemp은 사본을 할당합니다. roOutputValue 복사본을 복사 한 다음 tTemp의 소멸자가 첫 번째 복사본을 해제합니다. 당신이 만들고 tTemp을 파괴하여 시간을 낭비하지만

는, 당신은 방금 쓴 수 : 나는 "진짜 코드를"믿고있어

if (SysStringLen(tvInputValue.bstrVal) > 0) 
    roOutputValue = tvInputValue.bstrVal; 

실제로 변형이 시점에서 BSTR을 보유하고 확인합니다.

+0

예 sysalloc 및 sysfree는 BSTR에 대해 의미가 있으며 _bstr_t는이 작업을 수행하는 래퍼입니다. 둘째, 하단의 코드는 프로젝트의 코드를 축 어적으로 사용합니다. 마지막으로, 코드에 원격 디버거를 연결하면 ReadFromDatabase 및 GetValueFromVariant에서 가장 큰 크기로 스택보기를 표시하는 유일한 2 개의 지점 ... 변수의 모든 크기는 그대로 유지되지만 메모리는 증가합니다. . –

+0

더 나아가 스택 뷰를 통과 할 때 드롭 다운을 사용하여 힙 공간 크기 증가가 _bstr_t에서 유래하는 곳을 확인하면 _bstr_t :: _ bstr_t -> _bstr_t :: Data_t :: Data_t이므로 힙 크기가 증가하므로 이 _bstr_t의 디버거에서 명확하게 볼 수 있습니다. –

+0

@RAZ_Muh_Taz 좋습니다. 'VT_BSTR'이 variant 유형인지 확인하는 코드를 추가해야합니다. (실제로 매크로가 있다고 생각합니다.) 실제로 bstr을 사용하기 전에 –