Re: Как искать поехавшую память?
От: B0FEE664  
Дата: 20.09.13 13:26
Оценка: 5 (2) +3
Здравствуйте, Arturchik, Вы писали:

A>Например, такой код:


A>
A>myClass = class
A>{
A>  void myClass() {}
A>  double a;
A>}
A>...
A>myClass* с;
A>с = new myCalss();
A>c.a = 1.2;
A>


Ничего не понимаю. Это точно С++?

A>Точка останова на строку после последней, чтобы посмотреть чему равно значение c.a. Равно оно не 1.2, а чему-то левому.

Удивительное рядом. Как оно вообще скомпилировалось ?

A>Все это находится в большом проекте. Глазами уже устал искать ошибку. Подскажите, как бы Вы поступили в такой ситуации, что смотреть, за что хвататься?

Я бы первым делом проверил, что дебажу тот же самый код, что вижу на экране.
И каждый день — без права на ошибку...
Как искать поехавшую память?
От: Arturchik Россия  
Дата: 20.09.13 11:55
Оценка: -1
Всем привет. Недавно пришел к проблеме из которой пока не смог выпутаться.

Например, такой код:


myClass = class
{
  void myClass() {}
  double a;
}
...
myClass* с;
с = new myCalss();
c.a = 1.2;


Точка останова на строку после последней, чтобы посмотреть чему равно значение c.a. Равно оно не 1.2, а чему-то левому.

Все это находится в большом проекте. Глазами уже устал искать ошибку. Подскажите, как бы Вы поступили в такой ситуации, что смотреть, за что хвататься?
Re[4]: Как искать поехавшую память?
От: Кодт Россия  
Дата: 20.09.13 12:59
Оценка: +1
Здравствуйте, Arturchik, Вы писали:

A>Забыл добавить.

A>Еще в myClass описан пустой виртуальный деструктор. Так вот, если его убрать, то здесь все работает, но повторяется ошибка в другом месте.

Виртуальный деструктор => наличие виртуальных функций => указатель на таблицу виртуальных функций vfptr по нулевому смещению в теле класса.
Попробуй вместо деструктора в самое начало класса добавить void* dummy.

Кстати говоря, если отлаживать в релизе, т.е. со включёнными оптимизациями, там могут быть редкостные чудеса.
Надеюсь, этот фактор уже учтён?
Перекуём баги на фичи!
Re: Как искать поехавшую память?
От: enji  
Дата: 20.09.13 12:00
Оценка:
Здравствуйте, Arturchik, Вы писали:

A>Точка останова на строку после последней, чтобы посмотреть чему равно значение c.a. Равно оно не 1.2, а чему-то левому.


A>Все это находится в большом проекте. Глазами уже устал искать ошибку. Подскажите, как бы Вы поступили в такой ситуации, что смотреть, за что хвататься?


ну к примеру ставишь точку останова на изменение адреса c.a и смотришь, где сработало
Re[2]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 20.09.13 12:33
Оценка:
Здравствуйте, enji.

Не срабатывает остановка. Значение после создания объекта = 0, после выполнения присваивания значение = ерудне, но точка останова на изменение c.a не срабатывает.
Re[3]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 20.09.13 12:36
Оценка:
Забыл добавить.
Еще в myClass описан пустой виртуальный деструктор. Так вот, если его убрать, то здесь все работает, но повторяется ошибка в другом месте.
Re[3]: Как искать поехавшую память?
От: saf_e  
Дата: 20.09.13 12:55
Оценка:
Здравствуйте, Arturchik, Вы писали:

A>Здравствуйте, enji.


A>Не срабатывает остановка. Значение после создания объекта = 0, после выполнения присваивания значение = ерудне, но точка останова на изменение c.a не срабатывает.


У вас скорее всего перетирается стек на котором лежит указатель на объект. Поставьте бряк на модификацию укзателя.

Т.е. на адрес: &c
Re: Как искать поехавшую память?
От: MTimur  
Дата: 20.09.13 13:01
Оценка:
Здравствуйте, Arturchik, Вы писали:

  Скрытый текст
A>Всем привет. Недавно пришел к проблеме из которой пока не смог выпутаться.

A>Например, такой код:


A>

A>myClass = class
A>{
A>  void myClass() {}
A>  double a;
A>}
A>...
A>myClass* с;
A>с = new myCalss();
A>c.a = 1.2;

A>


A>Точка останова на строку после последней, чтобы посмотреть чему равно значение c.a. Равно оно не 1.2, а чему-то левому.

A>Все это находится в большом проекте. Глазами уже устал искать ошибку. Подскажите, как бы Вы поступили в такой ситуации, что смотреть, за что хвататься?

Так.. на всякий случай.. Сборка то дебажная?
Re: Как искать поехавшую память?
От: Ops Россия  
Дата: 21.09.13 20:16
Оценка:
Здравствуйте, Arturchik, Вы писали:

A>Например, такой код:


A>

A>myClass = class
A>{
A>  void myClass() {}
A>  double a;
A>}
A>...
A>myClass* с;
A>с = new myCalss();
A>c.a = 1.2;

A>


Что за язык? Ты разделом не ошибся?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 23.09.13 08:06
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, Arturchik, Вы писали:


A>>Например, такой код:


A>>

A>>myClass = class
A>>{
A>>  void myClass() {}
A>>  double a;
A>>}
A>>...
A>>myClass* с;
A>>с = new myCalss();
A>>c.a = 1.2;

A>>


Ops>Что за язык? Ты разделом не ошибся?


Извините, писал от руки =)

Настоящий код такой:

TurbulenceInfo.h
class TurbulenceInfo
{
public:
    TurbulenceInfo(void);
    virtual ~TurbulenceInfo(void);
    CTime time;
    double TO;    // turbulence onset
    double TS;    // turbulence slope
    double TJ;    // turbulence jump
    int TT;        // turbulence timing
    int index;
    int TSIndex;
    bool appropriate;
}


TurbulenceInfo.cpp
TurbulenceInfo::TurbulenceInfo(void)
{
    TO = 0;    // turbulence onset
    TS = 0;    // turbulence slope
    TJ = 0;    // turbulence jump
    TT = 0;        // turbulence timing
    index = 0;
    TSIndex = 0;
    appropriate = false;
}

TurbulenceInfo::~TurbulenceInfo( void )
{

}


usage
TurbulenceInfo* ti = new TurbulenceInfo();
ti->TO = 12.235;


адрес ti->TO не изменяется, Data Breakpoint &ti->TO на присваивании не срабатывает...

Еще раз прошу прощения за свою непунктуальность
Re[5]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 23.09.13 08:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Виртуальный деструктор => наличие виртуальных функций => указатель на таблицу виртуальных функций vfptr по нулевому смещению в теле класса.

К>Попробуй вместо деструктора в самое начало класса добавить void* dummy.

К>Кстати говоря, если отлаживать в релизе, т.е. со включёнными оптимизациями, там могут быть редкостные чудеса.

К>Надеюсь, этот фактор уже учтён?

Добавил void* dummy в начало класса, убрал деструктор. Такая же свистопляска. Какой я из этого должен сделать вывод?
Re[2]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 23.09.13 08:16
Оценка:
Здравствуйте, MTimur, Вы писали:

MT>Так.. на всякий случай.. Сборка то дебажная?


Да
Re[4]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 23.09.13 08:37
Оценка:
Здравствуйте, saf_e, Вы писали:

_>У вас скорее всего перетирается стек на котором лежит указатель на объект. Поставьте бряк на модификацию укзателя.


_>Т.е. на адрес: &c



Оператор new выделил память и вернул указатель на 0x0012ecd4
В конструкторе объекта &this = 0x0012ecdc
На операторе присваивания через Immediate Window адрес объекта 0x0012ed28, а если мышку навести на экземпляр класса в коде, то в плавающем окошке адрес = 0x0ad50870.

Поставил брейкпоинт на изменение адреса pResult в операторе new. Брейк сработал в atltime.inl:

ATLTIME_INLINE CTime::CTime() throw() :
    m_time(0)
{
}


h-файл моего класса сейчас выглядит так:


class TurbulenceInfo
{
public:
    void* dummy;

    TurbulenceInfo(void);
    //virtual ~TurbulenceInfo(void);

    CTime time;
    double TO;    // turbulence onset
    double TS;    // turbulence slope
    double TJ;    // turbulence jump
    int TT;        // turbulence timing
    int index;
    int TSIndex;
    bool appropriate;
};
Re[6]: Как искать поехавшую память?
От: Кодт Россия  
Дата: 23.09.13 08:43
Оценка:
Здравствуйте, Arturchik, Вы писали:

A>Добавил void* dummy в начало класса, убрал деструктор. Такая же свистопляска. Какой я из этого должен сделать вывод?


Вывод такой, что виной всему лэяут класса.

Больше всего похоже на нарушение ODR.
Где-то существует определение этого класса, в котором этого указателя нет.
Например, какой-нибудь объектный файл, который почему-то не перекомпилируется (сбитая дата, сломанные зависимости, DLL hell и т.п.)
Перекуём баги на фичи!
Re[7]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 23.09.13 09:44
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вывод такой, что виной всему лэяут класса.


К>Больше всего похоже на нарушение ODR.

К>Где-то существует определение этого класса, в котором этого указателя нет.
К>Например, какой-нибудь объектный файл, который почему-то не перекомпилируется (сбитая дата, сломанные зависимости, DLL hell и т.п.)

Может быть проблема в следующем:
Я использую второй проект (Managed C++) для связи с модулями на C#. Там есть такой код:

#ifdef _MANAGED
    //Эти функции существуют только в управляемом коде
    CManagedObject(System::Object^ managed);
    System::Object^ GetObject() const {return managed_;}
#endif //_MANAGED


То есть, для моего проекта (native C++) модуль с приведенным выше кодом будет скомпилирован отдельно, в урезанном виде?
Re[3]: Как искать поехавшую память?
От: B0FEE664  
Дата: 23.09.13 18:15
Оценка:
Здравствуйте, Arturchik, Вы писали:

A>Настоящий код такой:

  Скрытый текст
C такими названиями переменных чудес стоит ждать.

А точки с запятой, таки, не хватает.
Ну да ладно.
Попробуйте перенести "CTime time;" в конец класса и добавить m_dummy_debug:
class TurbulenceInfo
{
public:
    TurbulenceInfo(void);
    virtual ~TurbulenceInfo(void);
    double TO;    // turbulence onset
    double TS;    // turbulence slope
    double TJ;    // turbulence jump
    int TT;        // turbulence timing
    int index;
    int TSIndex;
    bool appropriate;
    CTime time;
    char m_dummy_debug[64];
};


После этого следует проверить, произойдёт ли присваивание и что будет записано в m_dummy_debug.
И каждый день — без права на ошибку...
Re[4]: Как искать поехавшую память?
От: Кодт Россия  
Дата: 23.09.13 19:36
Оценка:
Здравствуйте, B0FEE664, Вы писали:

Дебажные блоки нужно добавить и спереди, и сзади
class TurbulenceInfo
{
public:
    TurbulenceInfo(void);
    virtual ~TurbulenceInfo(void);

    char m_dummy_debug_1[64];
    double TO;    // turbulence onset
    double TS;    // turbulence slope
    double TJ;    // turbulence jump
    int TT;        // turbulence timing
    int index;
    int TSIndex;
    bool appropriate;
    CTime time;
    char m_dummy_debug_2[64];
};

/////////

TurbulenceInfo::TurbulenceInfo(void)
{
    // заполняем дебажные блоки калиброванным мусором
    memset(m_dummy_debug_1, 0xCD, sizeof(m_dummy_debug_1));
    memset(m_dummy_debug_2, 0xB5, sizeof(m_dummy_debug_2));
    // и далее - обычная инициализация всего
    .....
}
Перекуём баги на фичи!
Re[3]: Как искать поехавшую память?
От: alexku Россия  
Дата: 23.09.13 21:52
Оценка:
Здравствуйте, Arturchik, Вы писали:


A>адрес ti->TO не изменяется, Data Breakpoint &ti->TO на присваивании не срабатывает...


A>Еще раз прошу прощения за свою непунктуальность


С какой стати адрес ti->TO должен изменяться? И нахрена тебе нужен дата брейкпойнт?
Лучше ответь себе на вопрос, сколько раз ты выполняешь new TurbulenceInfo() и сколько после этого выполняешь delete для твоих турбуленсинфо? Судя по приведённым огрызкам кода — ни разу.
Re[4]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 24.09.13 08:43
Оценка:
Здравствуйте, alexku, Вы писали:

A>С какой стати адрес ti->TO должен изменяться? И нахрена тебе нужен дата брейкпойнт?

A>Лучше ответь себе на вопрос, сколько раз ты выполняешь new TurbulenceInfo() и сколько после этого выполняешь delete для твоих турбуленсинфо? Судя по приведённым огрызкам кода — ни разу.

1.
Самый первый ответ был от enji:
A>ну к примеру ставишь точку останова на изменение адреса c.a и смотришь, где сработало

Может я что-то неправильно понял -- поправьте. Адрес c.a (эквив. ti->TO) не изменился.
Дата брейкпоинт должен сработать при изменении значения переменной c.a (ti->TO в новом варианте), но присваивание выполнил, а брейкпоинт не сроботал.

2.
Отвечу себе на этот вопрос вслух: new выполняю один раз, delete выполняй-не выполняй, результат не меняется
Re[5]: Как искать поехавшую память?
От: Arturchik Россия  
Дата: 24.09.13 10:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, B0FEE664, Вы писали:


К>Дебажные блоки нужно добавить и спереди, и сзади

К>
К>class TurbulenceInfo
К>{
К>public:
К>    TurbulenceInfo(void);
К>    virtual ~TurbulenceInfo(void);

К>    char m_dummy_debug_1[64];
К>    double TO;    // turbulence onset
К>    double TS;    // turbulence slope
К>    double TJ;    // turbulence jump
К>    int TT;        // turbulence timing
К>    int index;
К>    int TSIndex;
К>    bool appropriate;
К>    CTime time;
К>    char m_dummy_debug_2[64];
К>};

К>/////////

К>TurbulenceInfo::TurbulenceInfo(void)
К>{
К>    // заполняем дебажные блоки калиброванным мусором
К>    memset(m_dummy_debug_1, 0xCD, sizeof(m_dummy_debug_1));
К>    memset(m_dummy_debug_2, 0xB5, sizeof(m_dummy_debug_2));
К>    // и далее - обычная инициализация всего
К>    .....
К>}
К>


Получилось так:
  • в m_dummy_debug_1 последние 4 байта изменились. Попробовал
    (double&)&ti->m_dummy_debug_1[60]

    И, действительно, получил то, что должно быть в TO, т.е. все съехало на 4 байта.
  • m_dummy_debug_2 не изменился.

    Добавил void* dummy; в начало класса. Выполняю присваивание ti->time = (CTime)123456; Получилось так:
  • m_dummy_debug_1 не изменился.
  • m_dummy_debug_2 первые 8 байт обнулилиись.
  • ti->time = ерунда
  • (__time64_t&)&ti->m_dummy_debug_2[-11] = то, что я записывал в ti->time
  • Re[6]: Как искать поехавшую память?
    От: B0FEE664  
    Дата: 24.09.13 11:19
    Оценка:
    Здравствуйте, Arturchik, Вы писали:

    A>Получилось так:

    A>
  • в m_dummy_debug_1 последние 4 байта изменились. Попробовал
    A>
    A>(double&)&ti->m_dummy_debug_1[60]
    A>

    A>И, действительно, получил то, что должно быть в TO, т.е. все съехало на 4 байта.
    A>
  • m_dummy_debug_2 не изменился.

    Я предполагаю следующие причины:
    1) переопределённый operator new
    2) неверно заданное выравнивание в опциях компиляции
    3) нарушение ODR
  • И каждый день — без права на ошибку...
    Re[6]: Как искать поехавшую память?
    От: Кодт Россия  
    Дата: 24.09.13 15:16
    Оценка:
    Здравствуйте, Arturchik, Вы писали:

    <>

    Очень похоже на нарушение ODR.
    По причинам:
    — или что-то перекомпилируется с отставанием на такт
    — или где-то стоит #define double float или какое-нибудь похожее заподло
    — или где-то включена #pragma pack, и она распространилась на твою структуру, — а где-то она не включена и не распространилась
    Перекуём баги на фичи!
    Re[5]: Как искать поехавшую память?
    От: alexku Россия  
    Дата: 25.09.13 02:36
    Оценка:
    Прошу прощения, с первого раза не вкурил, о чём речь.
    Видимо TurbulenceInfo объявлена где-то ещё с другим набором или порядком мемберов. Попробуй своё объявление обернуть в namespace и указывать его явно при использовании. Или назови по-другому.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.