두 개의 작은 VC++ 응용 프로그램이 있습니다. 첫 번째 부분은 주요 기능을 포함하며 정적 라이브러리로 컴파일됩니다. 두 번째 부분은 조각 서비스에서 라이브러리로 연결되는 Windows 서비스입니다.관련이없는 라이브러리 객체의 정적 변수 손상 (또는 그 반대)
메모리 손상으로 인해 이상한 행동이 나타납니다. 데이터 브레이크 포인트 등을 설정함으로써 라이브러리 객체 중 하나의 특정 멤버가 2 개 작성 될 때마다 서비스 피스의 정적 변수가 손상되고 있음을 확인할 수있었습니다. 반대로 정적 var이 가리키는 위치가 기록 될 때 라이브러리 객체의 멤버가 손상됩니다. 개체가 겹칠 수 있습니까?
편집 : BlahHelper의 인스턴스가 내 서비스 코드의 전역 범위에 있다는 것을 잊어 버렸습니다. BlahHelper와 ServiceBase :: m_service는 모두 exe의 전역 데이터 영역에 있어야하기 때문에 중복 이론을 지원합니다.
EDIT2 : 원시 메모리를보고 모든 관련 개체의 주소를 확인하면 BlahHelper 개체가 ServiceBase :: m_service 포인터와 겹치는 것을 확인했습니다. 왜 이것이 사실일까요?
여기에 관심있는 클래스 정의입니다 :
// This is the basis of my service. I derive from this and override
// the start() and stop() methods to implement the service.
class ServiceBase
{
public:
virtual ~ServiceBase();
static void Run(ServiceBase& service);
protected:
ServiceBase(DWORD controlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN);
virtual void Start(DWORD control) = 0;
virtual void Stop(DWORD control) = 0;
void UpdateState(DWORD state,
HRESULT errorCode = S_OK);
const std::wstring& ServiceName() const;
private:
void SetServiceStatus();
static void WINAPI ServiceMain(DWORD argumentCount,
PWSTR* arguments);
static void WINAPI Handler(DWORD control);
static ServiceBase* m_service; // This is being corrupted
SERVICE_STATUS_HANDLE m_handle;
ServiceStatus m_status;
std::wstring m_serviceName;
};
이 라이브러리의 클래스 중 하나입니다. 라이브러리를 내 서비스 exe에 연결하고 BlahHelper 객체를 인스턴스화하면 메모리 손상과 관련된 이상한 문제가 발생합니다. 내가 말했듯이
// Writing to _blah2Open or _blah1Open causes corruption of ServiceBase::m_status
class BlahHelper
{
// Names changed to protect the innocent
public:
BlahHelper();
~BlahHelper();
HRESULT GetSomeInfo();
HRESULT GetSomeStatus(LPWORD statPosition);
void Init(char blah1Sp[], char blah2Sp[], HWND messageWindow);
bool Blah1ConnectionOpen(){return _blah2Open;};
bool Blah2ConnectionOpen(){return _blah1Open;};
hash_map<string,short> GetSomeJunk(){return _someJunk;};
void Refreshblah1Config();
bool HasItemsTakenSensor(){return _blah1HasItemsTakenSensor;};
void Enterblah2();
void blah2Exited();
void Ackblah2ExitReq();
void Cleanup();
void Initblah1();
void Initblah2();
private:
LPWFSRESULT OpenSession(char* spName, HSERVICE* handle);
LPWFSRESULT Getblah1Caps();
void Cleanupblah1();
void Cleanupblah2();
void Closeblah1();
void Closeblah2();
void Openblah1();
void Openblah2();
void Registerblah1();
void Registerblah2();
void Checkblah1Caps();
void CheckSomeJunk();
void Getblah1Config();
void LogMessage(string message, int logLevel);
char* _SpName1;
char* _SpName2;
HWND _messageWindow;
HSERVICE _Handle1;
HSERVICE _Handle2;
bool _blah2Open; // writing to this causes corruption of ServiceBase::m_service
bool _blah1Open; // writing to this causes corruption of ServiceBase::m_service
const string _logSource;
const int _logMsgId;
bool _blah1HasItemsTakenSensor;
hash_map<string, short> _someJunk;
};
는 데이터 중단 점은 쓰기 _blah1Open 또는 _blah2Open 부패가 ServiceBase 것을 :: m_service를 한 것으로 밝혀졌습니다. 추가 확인으로서, 나는이 값들을 쓴 BlahHelper의 모든 구현 라인을 주석 처리했으며, 부패는 사라졌다.
BlahHelper 멤버의 선언 순서를 변경하더라도 메모리 손상 문제는 계속 발생하지만 증상은 변경됩니다.
서비스에 라이브러리 코드를 직접 포함하면 더 이상 문제가 표시되지 않습니다. 진단 목적 이외의 다른 목적으로는이 작업을 수행 할 수 없지만 링크 과정에서 이상한 점이 있음을 나타냅니다.
라이브러리를 링크하는 서비스 응용 프로그램이 유니 코드로 컴파일되는 동안 라이브러리는 Muli-Byte 문자 집합으로 컴파일된다는 점도 주목해야합니다. 이것은 변경하기가 어렵습니다.
왜 이런 일이 일어날 수있는 가능한 이유 또는 문제 진단 방법을 제안 할 수 있습니까? 메모리 손상이 있음을 깨달았을 때, 나는 버퍼 오버플로와 같은 간단한 원인을 원했다. 그러나, 나는 왜 한 물체가 다른 물체에 발을 디뎠을지 모른다.
m_service 자체가 변경됩니다. 또한 m_service 초기화는 _blah1Open 및 _blah2Open에 영향을줍니다. 몇 가지 메모리 어드레스 및 크기는 런타임 같습니다 및 m_service : 0x0053db84 크기 : 4 및 _blah1Open : 0x0053db86 크기 : 1 및 _blah2Open : 0x0053db85 크기 : 1 및 _blah1Handle : 0x0053db83 크기 : 2 및 _blah2Handle : 0x0053db81 크기 : 2 보시다시피, _blah1Open 및 _blah2Open은 m_service의 마지막 2 바이트에 있습니다. – Odrade