Visual Studio 2008 C ++错误报告内存地址位置

时间:2010-09-21 15:07:02

标签: c++ visual-studio-2008 visual-c++

我正在尝试使用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。它基本上践踏了连续的内存区域(因而也就是变量)

2 个答案:

答案 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;
    };