Visual Studio 2008 C ++ неверно сообщает расположение адресов памяти - PullRequest
1 голос
/ 21 сентября 2010

Я пытаюсь отладить проблему с перезаписью стека (без каламбура) в коде c / c ++ в Visual Studio 2008.

Когда я компилирую решение в режиме отладки win32, я могу запустить отладчик и увидеть, как создается экземпляр класса.

В вызове конструктора мы инициализируем некоторые переменные-члены char [] фиксированной длины, используя memset.

Если я использую printf для печати ячейки памяти переменной-члена, я получаю значение, которое на 14 байт превышает то, что окно просмотра / локального var VS2008 сообщает как ячейку памяти.

Как 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 Locals

m`_szServer 0x014272fa ""   char [128]`

Он выключен на 14 ... и когда код на самом деле запускает самый первый memset, он делает это, начиная с адреса 7308, а не 72fa. Это в основном попирает смежные области памяти (и, следовательно, переменные)

Ответы [ 2 ]

1 голос
/ 21 сентября 2010

Отладчик вставляет дополнительное пространство.Это пространство имеет предопределенное значение, и если оно изменилось, отладчик знает, что что-то пошло не так.Для компиляторов и отладчиков нормально вставлять пространство, которое не имеет никакой очевидной цели.

Если вы использовали символ фиксированного размера [], это сразу сигнализирует мне как о проблеме, поскольку явной инкапсуляции нет.Вы можете использовать пользовательский тип массива (например, boost :: array) для написания собственного кода обнаружения переполнения буфера.Если вы бросите в это время, вы получите трассировку стека.

0 голосов
/ 21 сентября 2010

Это (вероятно) не исправит вашу ошибку, но я постараюсь избегать массивов в стиле 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;
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...