Странное поведение std::vector в DEBUG`е
От: Tujh Голландия  
Дата: 18.02.08 15:46
Оценка:
Есть некоторые классы для TCP сервера со следующим кодом:

// указатель на текущий класс
ik_server *g_pMainServer = NULL;

// функции

// обновить данные клиента
void updateClientData(ik_data_t &client_data)
{
    if (g_pMainServer)
        g_pMainServer->updateClientData(client_data);
};

// получить данные клиента
ik_data_t createDefaultClientData(unsigned long client_id)
{
    if (g_pMainServer)
        return g_pMainServer->createDefaultClientData(client_id);
    return ik_data_t();
};

// класс ik_server

    // предикант поиска в классе ik_server
    struct _find_pred //: std::binary_function<unsigned long, unsigned long, bool>
    {
        unsigned long   searchID;   //

        // конструктор
        explicit _find_pred(const unsigned long ID)
        {
            searchID = ID;
        };

        //
        bool operator () (const ik_data_t &ik)
        {
            if (ik.ik_id == searchID)
                return true;
            return false;
        };
    };

    // тип данных - массив клиентов
    typedef std::vector<ik_data_t> clientArray;

// конструктор
ik_server::ik_server()
{
    ...
    g_pMainServer = this; // установить указатель на класс
};

// деструктор
ik_server::~ik_server()
{
    g_pMainServer = NULL; // удалить указатель на класс
    ...
};

// получить данные клиента
ik_data_t ik_server::createDefaultClientData(unsigned long client_id)
{
    // защитить процедуру при множестве потоков
    // собственные классы, работают без замечаний
    critical_section_keeper tmp(&m_class_section);
        clientArray::iterator itData = m_clientArray.end();
        ik_data_t Result;
        // поиск с использованием предиканта
        itData = std::find_if(m_clientArray.begin(), m_clientArray.end(), _find_pred(client_id));
        // если клиент уже имеется в массиве - вернуть его данные
        if (itData != m_clientArray.end())
        {
            Result = (*itData);
        }
        // клиента нет в массиве - создать новую структуру
        else
        {
            Result.ik_id = client_id;
            m_clientArray.push_back(Result);
        };
        return Result;
};

// обновить данные клиентов
void ik_server::updateClientData(ik_data_t &client_data)
{
    critical_section_keeper tmp(&m_class_section);
        clientArray::iterator itData = m_clientArray.end();
        // поиск
        itData = std::find_if(m_clientArray.begin(), m_clientArray.end(), _find_pred(client_data.ik_id));
        if (itData != m_clientArray.end())
        {
            // в RELEASE попадаем сюда
            MessageBoxW(0, L"Update client data", L"IK Server", MB_OK);
            (*itData) = client_data;
        }
        else
        {
            // сюда по идее попадать не должны, но попадаем
            // всегда в DEBUG
            MessageBoxW(NULL, L"Error: IK ID not found", L"IK Server", MB_OK);
        };
};

// класс ik_thread (отдельный поток)

// "шаг" потока
void ik_thread::nextStep()
{
    int iResult = 0;
    // получить сообщение от клиента
    iResult = recv(m_client_ik.client_socket, &m_buffer[0], ul_buffer_size, 0);

    // temporary
    std::cout << "receiving: " << iResult << " bytes from ik." << std::endl;

    if (iResult != 0)
    {
        unsigned long  l_id = 0;
        unsigned char  ch_v = 0;
        unsigned short sh_v = 0;
        char *pID = new char[ul_buffer_size];

        // получить ID клиента
        memcpy(pID, &m_buffer[0], 9);
        pID[9] = 0x00;
        l_id = atol(pID);

        // temporary
        std::cout << "ik UIN = " << l_id << std::endl;

        //
        ik_data_t ik_t = createDefaultClientData(l_id);

        /*
         * логика опроса
         */

        // temporary
        std::cout << "send DATA\\n to ik..." << std::endl;

        // получить данные клиента
        memcpy(pID, "DATA\n", 6);
        iResult = send(m_client_ik.client_socket, pID, 6, 0);
        if (iResult != SOCKET_ERROR)
        {
            // temporary
            std::cout << "DATA\\n is sending" << std::endl;
        };
...
        delete[] pID;
        updateClientData(ik_t);
    };
    shutdown(m_client_ik.client_socket, SD_SEND);
    closesocket(m_client_ik.client_socket);
    m_transferComplite = true;
...

Код отладочный, для проверки работы, потом будет оптимизироваться...

Проблема в следующем:
MSVC2003 (VC7.1)
в DEBUG режиме функция ik_server::updateClientData получает _пустой_ вектор m_clientArray, при этом в ik_server::createDefaultClientData данные создаются и заносятся в вектор корректно (смотрел дебагером), при этом даже m_clientArray.end(), являющийся единственным элементом, отличается от того, что был на выходе ik_server::createDefaultClientData.
В RELEASE однако, поиск работает как положено (данные обновляются), но адреса и содержимое вектора просмотреть невозможно естественно.

З.Ы. есть вторая проблема в MSVC2008 (VC9.0)
Опять же в DEBUG в строке memcpy(pID, "DATA\n", 6) pID равен NULL хотя до входа в ik_data_t ik_t = createDefaultClientData(l_id) он корректен.

Думается, что где-то течет или портится память, но тогда не понятно, почему я не вижу ни одной ошибки в RELEASE и более того, релизный вариант работает как задумывалось, а дебажный — нет.
Может кто сталкивался с подобным поведением вектора и подскажет метод поиска и устранения ошибки?
Re: Странное поведение std::vector в DEBUG`е
От: Аноним  
Дата: 19.02.08 10:20
Оценка:
Здравствуйте, Tujh, Вы писали:

T>Есть некоторые классы для TCP сервера со следующим кодом:


T>Код отладочный, для проверки работы, потом будет оптимизироваться...


T>Проблема в следующем:

T>MSVC2003 (VC7.1)
T>в DEBUG режиме функция ik_server::updateClientData получает _пустой_ вектор m_clientArray, при этом в ik_server::createDefaultClientData данные создаются и заносятся в вектор корректно (смотрел дебагером), при этом даже m_clientArray.end(), являющийся единственным элементом, отличается от того, что был на выходе ik_server::createDefaultClientData.
T>В RELEASE однако, поиск работает как положено (данные обновляются), но адреса и содержимое вектора просмотреть невозможно естественно.

T>З.Ы. есть вторая проблема в MSVC2008 (VC9.0)

T>Опять же в DEBUG в строке memcpy(pID, "DATA\n", 6) pID равен NULL хотя до входа в ik_data_t ik_t = createDefaultClientData(l_id) он корректен.

T>Думается, что где-то течет или портится память, но тогда не понятно, почему я не вижу ни одной ошибки в RELEASE и более того, релизный вариант работает как задумывалось, а дебажный — нет.

T>Может кто сталкивался с подобным поведением вектора и подскажет метод поиска и устранения ошибки?

Оптимизацию отключили в дебажном таргете?
Re[2]: Странное поведение std::vector в DEBUG`е
От: Аноним  
Дата: 20.02.08 04:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Оптимизацию отключили в дебажном таргете?


Естественно.
Re: Странное поведение std::vector в DEBUG`е
От: _Vasilyev Ниоткуда  
Дата: 20.02.08 21:00
Оценка:
Здравствуйте, Tujh, Вы писали:

T> memcpy(pID, "DATA\n", 6);

я обычно добавляю pID[ 6 ] = '\0', для политкорректности.
Re: Странное поведение std::vector в DEBUG`е
От: Drey  
Дата: 25.02.08 08:23
Оценка:
Здравствуйте, Tujh, Вы писали:


T>Думается, что где-то течет или портится память, но тогда не понятно, почему я не вижу ни одной ошибки в RELEASE и более того, релизный вариант работает как задумывалось, а дебажный — нет.

T>Может кто сталкивался с подобным поведением вектора и подскажет метод поиска и устранения ошибки?

Я бы проверил количество приходящих байт в nextStep() (переменная iResult) и значение переменной ul_buffer_size.
В приведенном коде — утечки могут быть только тут — потому что дальше без проверок используются константы при обращении с буфером — вначале строго 9 байт, потом строго 6 байт.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.