Сейчас на форуме: zds (+5 невидимых)

 [email protected] —› Программирование —› Неверное объявление переменных в стеке
Посл.ответ Сообщение

Ранг: 17.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 02 марта 2014 21:32 · Поправил: Wagos
· Личное сообщение · #1

Добрый вечер. Создал отдельную тему для данного вопроса. Продолжаю войну с компилятором Embarcadero (или со своей невнимательностью). Проблема следующая: в конструкторе класса производится инициализация внутренних переменных класса (public).
К примеру: a = 1. При компиляции имеем следующие команды:

Code:
  1. = 1;
  2.  
  3. 0040308C 8B4D08           mov ecx,[ebp+$08]
  4. 0040308F C7412C01000000   mov [ecx+$2c],$00000001


Программа пишет значение 1 в память, причем адрес ячейки отличается от &a на 18h (&a_real - &a = 18h, где &a_real - адрес реальной ячейки памяти, куда пишется значение; &a - адрес ячейки памяти, в которую должно писаться значение, но не пишется). Экземпляр класса создается через операцию new в обработчике события создания формы.
Причем, программа работает нормально - все аргументы нормально передаются в функции и обрабатываются (пока сбоев на этой почве не обнаружил). Программу невозможно отлаживать - в Watch'ах вместо нормальных значений выводится всякий мусор.

+ бонусный глюк, который удалось обнаружить. При добавлении некоторых переменных(внутренних public'овых переменных класса) в Watch в Embarcadero'вский отладчик, он начинает ругаться, что таких переменных вообще не существует (Добавляю в Watch, как this->var, или object->var), хотя, при компиляции данные переменные были отлично обработаны.

У кого возникали подобные проблемы?




Ранг: 337.6 (мудрец), 224thx
Активность: 0.210.1
Статус: Участник
born to be evil

Создано: 02 марта 2014 23:15 · Поправил: ajax
· Личное сообщение · #2

либо я _сильно_ не трезв, либо кто-то упускает стек на вставленные ембо-регистры. плюс, методы или как там их в классах, как бэ по оффсетам хранятся

-----
От многой мудрости много скорби, и умножающий знание умножает печаль




Ранг: 71.2 (постоянный), 33thx
Активность: 0.050.12
Статус: Участник

Создано: 02 марта 2014 23:22 · Поправил: kunix
· Личное сообщение · #3

А родительский класс есть? Не может ли быть такое, что все классы наследуются от TObject, или как там у вас?
Вообще компиллер может сдвинуть все поля на более старшие смешения, это его право (всмысле, можно задать такое ABI). Может в младших смешения хранится RTTI какое-то.



Ранг: 17.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 02 марта 2014 23:36 · Поправил: Wagos
· Личное сообщение · #4

ajax, Не понял, можно ещё раз? Что кто упускает?

kunix, Нет, родительского класса нет. Объект непосредственно от написанного класса, который ни от чего не наследуется.
Проблем не было, пока не написал пару рекурсивных функций в классе. (которые используются намного позже инициализации) Снес эти функции - проблемы всё равно остались и так и не исчезли. По поводу RTTI - хз. По-идее, в отладчик должна передаваться информация, которую можно использовать для отладки. Хотя, возможно, отладчик на@бнулся, но я с таким ни разу не сталкивался.

Откомпилировал с помощью GNU - та-же проблема. Видимо, что-то с настройками компилятора.




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 03 марта 2014 09:32 · Поправил: DenCoder
· Личное сообщение · #5

Wagos
Если ничего не упустили, то могу предположить только одну возможную причину:
компилятор резервирует некоторую область для своих целей

Что в 6 двордах до переменной?

1. Embarcadero Delphi (ранее наз. CodeGear Delphi и Borland Delphi) — наверное, самый известный компилятор, который является последователем Borland Pascal и Turbo Pascal.
2. Турбо Паскаль, начиная с версии 5.5, добавил в Паскаль объектно-ориентированные свойства, а в Object Pascal — динамическую идентификацию типа данных с возможностью доступа к метаданным классов (то есть к описанию классов и их членов) в компилируемом коде, также называемом интроспекцией — данная технология получила обозначение RTTI. Так как все классы наследуют функции базового класса TObject, то любой указатель на объект можно преобразовать к нему, после чего воспользоваться методом ClassType и функцией TypeInfo, которые и обеспечат интроспекцию.

Я бы провёл исследование, в каком порядке в скомпилированном коде хранится. Домашнее задание Вам
1) --> Динамическая идентификация типа данных <--. А также интересны её формат и размер. (что-то подсказывает, что аналогично Delphi, но без отрицательных смещений)
2) Таблица методов-членов класса. Указатель на таблицу или целиком массив?
3) Поля-члены класса
4) Таблица методов-членов родительского класса TObject. Указатель на таблицу или целиком массив?
5) Поля-члены родительского класса.

-----
IZ.RU


| Сообщение посчитали полезным: Wagos

Ранг: 17.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 03 марта 2014 23:22
· Личное сообщение · #6

DenCoder, Спасибо, посмотрим, что получится



Ранг: 17.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 04 марта 2014 13:59 · Поправил: Wagos
· Личное сообщение · #7

Решение найдено. Приношу извинения разработчикам компилятора за желание их расстрелять и четвертовать. С помощью универсального способа поиска неисправностей (всё закомментировать и раскомментировать до тех пор, пока не появятся ошибки), решение было найдено.

Причина проблемы оказалась в следующем:
Программа состоит из 3-х модулей: VCL(с формой), мой класс и отдельным модулем идут потоки, наследуемые от класса TThread. О них-то я и забыл. Также, эти модули используют 2 header'a: первый - стандартный (создается при создании проекта), второй - описывает переменные класса и потоков.
Однажды мне пришлось обновить header класса и потоков, внеся туда некоторые изменения. Я сохранил его как отдельный файл и обновил #include в cpp-файле класса, забыв при этом обновить его в файле потоков!!!
Поначалу проблемы были незаметны, но, вписав туда большую структуру, у меня поплыли адреса, т. к. класс - использует один header, а потоки - используют другой. Вот, собственно и всё. Builder - невиновен. Внимательность - залог всего.


 [email protected] —› Программирование —› Неверное объявление переменных в стеке
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати