我正在尝试使用Visual Studio 2008中的某些c / c ++代码调试堆栈覆盖(没有双关语)损坏问题。
当我在win32调试模式下编译解决方案时,我能够运行调试器并看到一个类实例化。
在构造函数调用中,我们使用memset初始化一些固定长度的char []成员变量。
如果我使用printf打印成员变量的内存位置,我得到的值恰好是VS2008 watch / local var窗口报告为内存位置的14个字节。
VS如何计算它认为内存地址是变量的内容?
编辑:我已经使用运行时检查选项编译,我看到的是“运行时检查失败#2 - 变量'varName'的堆栈已损坏。
编辑3:这是缩写源
标题文件:
//////////////////////////////////////////////////////////////////////
#include "commsock.h"
#include "buffer.h"
#include "BufferedReader.h"
#define AUTHTYPE_PASSKEY 1
#define AUTHTYPE_PAGER 2
#define AUTHTYPE_PASSWORD 3
#define AUTHTYPE_RADIUS 4
#define AUTHTYPE_INFOCARD_RO 5
#define AUTHTYPE_INFOCARD_CR 6
#define AUTHSTATE_NOT_LOGGED_IN 0
#define AUTHSTATE_IDENTIFIED 1
#define AUTHSTATE_AUTHENTICATED 2
#define AUTHSTATE_MAX_FAILS 32
#define AUTHSTATE_NO_LOG 65536
class PRClientSession {
public:
PRClientSession();
virtual ~PRClientSession();
void Reset();
BOOL BeginAuth(LPCSTR szUserID, LPCSTR szClientIP, LPCSTR szOtherUserID="");
BOOL CompleteAuth(LPCSTR szResponse);
BOOL Logoff();
BOOL DetachAsync();
BOOL Detach();
BOOL Attach(const char *authstr=NULL);
BOOL Connected(){return m_Socket.Connected();};
BOOL EncryptText(char *pPassword, char *pOut, char *pKey);
BOOL EncryptText(char *pPassword, char *pOut);
BOOL DecryptText(char *pPassword, char *pOut, char *pKey);
BOOL DecryptText(char *pPassword, char *pOut);
LPCSTR Error(LPCSTR szErr=NULL){if (szErr)strncpy_s(m_szError,szErr,sizeof(m_szError));return m_szError;};
LPCSTR Challenge(LPCSTR szChal=NULL){if (szChal)strncpy_s(m_szChallenge,szChal,sizeof(m_szChallenge));return m_szChallenge;};
LPCSTR UserID(LPCSTR szUID=NULL){if (szUID)strncpy_s(m_szUserID,szUID,sizeof(m_szUserID));return m_szUserID;};
LPCSTR SessionID(LPCSTR szSID=NULL){if (szSID)strncpy_s(m_szSessionID,szSID,sizeof(m_szSessionID));return m_szSessionID;};
LPCSTR SessionLogID(LPCSTR szSLID=NULL){if (szSLID)strncpy_s(m_szSessionLogID,szSLID,sizeof(m_szSessionLogID));return m_szSessionLogID;};
LPCSTR SessionStateID(LPCSTR szSSID=NULL){if (szSSID)strncpy_s(m_szSessionStateID,szSSID,sizeof(m_szSessionStateID));return m_szSessionStateID;};
int AuthType(int iType=-1){if (iType != -1)m_iAuthType = iType;return m_iAuthType;};
int SendRequest(LPCSTR szType, ...);
int Write(char *szBuf, int iLen=-1);
int Read(char *szBuf, int iLen, int iTimeout=-1);
BOOL ReadResponse(int iBlock=FALSE);
int ReadResponseTimeout(int iBlock) ;
BOOL GetField(LPCSTR szField, char *szBuf, int iLen, int total=-1);
BOOL GetField(LPCSTR szField, int &iBuf );
char *GetData(){return m_pData;};
int GetDataSize(){return m_iDataSize;}
char *GetMessage(){return m_pMessage;};
SOCKET getSocket(){return m_Socket.getSocket();}
private:
BOOL LoadConfig();
BOOL GetMsgField(LPCSTR szIn, LPCSTR szSrch, char *szBuf, int iLen, int total=-1);
int ReadMessage( char *buf, int len, const char *terminator = NULL );
public:
bool sendCommand(char* szCommand, char *szArglist);
LPCSTR ReplyMessage(){ return m_szReplyMessage; }
int IsRadiusChallenge(){ return m_iIsRadiusChallenge; }
static char PRIISMS_USER_TAG[];
static char DEST_USER_TAG[];
static char RADIUS_USER_TAG[];
static char RADIUS_PASSWORD_TAG[];
static char GENERATE_LOGIN[];
static char VALIDATE_LOGIN[];
static char PR_RADIUS_GENERATED[];
private:
BOOL doConnect();
// Response reader vars...
char *m_pMessage;
char *m_pData;
Buffer m_Buf;
BOOL m_bLoaded;
BufferedReader m_reader;
Buffer m_ReqBuf;
CCommSocket m_Socket;
char m_szServer[128];
int m_iServerPort;
char m_szError[128];
int m_iAuthState;
int m_iDataSize;
int m_iAuthType;
char m_szChallenge[1024];
char m_szUserID[64];
char m_szSessionID[64];
char m_szSessionLogID[64];
char m_szSessionStateID[64];
char m_szSessionSecret[16];
long m_RequestID;
int m_iIsRadiusChallenge;
char m_szReplyMessage[1024];
};
和带有构造函数的源代码......
#include "stdafx.h"
#include "PRclntsn.h"
#include "iondes.h"
#include "prsystemparameters.h"
#include "prsessionlog.h"
#include "util.h"
#include "PRClntSn.h"
#include <string>
using namespace std;
#define LoadConfigFailedMsg "Unable to retrieve database configuration entries."
#ifndef AUTH_TYPE_RADIUS
#define AUTH_TYPE_RADIUS 4
#endif
//------------------------------------------------------------------------------------
// initialize static members
char PRClientSession::DEST_USER_TAG[] = "DEST_USER=";
char PRClientSession::PRIISMS_USER_TAG[] = "PRIISMS_USER=";
char PRClientSession::RADIUS_USER_TAG[] = "RADIUS_USER=";
char PRClientSession::RADIUS_PASSWORD_TAG[] = "RADIUS_PASSWORD=";
char PRClientSession::GENERATE_LOGIN[] = "GENERATE_LOGIN";
char PRClientSession::VALIDATE_LOGIN[] = "VALIDATE_LOGIN";
char PRClientSession::PR_RADIUS_GENERATED[] = "PR_RADIUS_GENERATED";
PRClientSession::PRClientSession()
{
Reset();
}
void PRClientSession::Reset()
{
//LOG4CXX_TRACE(mainlogger, CLASS_METHOD_TAG);
printf("m_szServer mem location: %p", (void *)&m_szServer);
memset(m_szServer, 0, sizeof(m_szServer));
m_iServerPort = 0;
memset(m_szError, 0, sizeof(m_szError));
m_iAuthState = 0;
m_iDataSize = 0;
m_iAuthType = 0;
memset(m_szChallenge, 0, sizeof(m_szChallenge));
memset(m_szUserID, 0, sizeof(m_szUserID));
memset(m_szSessionID, 0, sizeof(m_szSessionID));
memset(m_szSessionLogID, 0, sizeof(m_szSessionLogID));
memset(m_szSessionStateID, 0, sizeof(m_szSessionStateID));
memset(m_szSessionSecret, 0, sizeof(m_szSessionSecret) );
// memset(m_szReadBuf, 0, sizeof(m_szReadBuf));
m_RequestID = 0;
m_iIsRadiusChallenge = 0;
memset(m_szReplyMessage, 0, sizeof(m_szReplyMessage));
m_reader.setComm(&m_Socket);
}
printf的输出:
m_szServer mem location: 01427308
Visual Studio 2008本地窗口
m`_szServer 0x014272fa "" char [128]`
它关闭了14 ...当代码实际运行第一个memset时,它从地址7308开始,而不是72fa。它基本上践踏了连续的内存区域(因而也就是变量)
答案 0 :(得分:1)
调试器会插入额外的空间。此空间设置为预定义值,如果更改,调试器会知道出现了问题。编译器和调试器插入没有明显用途的空间是正常的。
如果您使用了固定大小的char [],则会立即向我发出问题,因为没有明确的封装。您可以使用自定义数组类型(例如boost :: array)来编写自己的缓冲区溢出检测代码。如果你在这个时候扔,你会得到一个堆栈跟踪。
答案 1 :(得分:0)
这可能(可能)不会修复你的错误,但如果可以,我会尽量避免使用C风格的数组。
除非你有一些令人信服的理由使用固定长度的数组,否则用std :: vector替换它们,默认情况下将填充0x00。
所以而不是
const size_t MYCLASS::BUFLEN(16);
class myClass {
public:
myClass()
{
memset(buffer, 0, BUFLEN);
}
private:
static const size_t BUFLEN;
char buffer[BUFLEN];
};
你有
const size_t MYCLASS::BUFLEN(16);
class myClass {
public:
myClass() : buffer(BUFLEN)
{
memset(buffer, 0, BUFLEN);
}
private:
static const size_t BUFLEN;
std::vector<char> buffer;
};