Форум программистов, компьютерный форум, киберфорум
Наши страницы

[C++] Взятие адреса конструктора. Физическое время существование объекта. - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Как узнать, какой функции какой файл *.a соответсвует? http://www.cyberforum.ru/cpp/thread446938.html
Друзья! Работаю с mingw, вот там надо так: если, допустим, вызываешь API- функцию, то надо подключать соответствующую библиотеку (?), делается это ключом линкёра примерно так: -lwww файл Эта...
C++ Про деструктор и утечку памяти Доброе время суток. Вот что дано: #include <string> #include <vector> class Symbols { protected: void add(std::string str); // добавления символа virtual void inputData() = 0; //... http://www.cyberforum.ru/cpp/thread446749.html
Создать exe, запускающий exe C++
Говорю сразу: я ничего не смыслю в програмировании; зачем подался на такой форум? Надеюсь получить ответ на свой вопрос,упавая на то, что его реализация не такая сложная. У меня возникла...
Странное поведение bool C++
Помогал отлаживать код и мы наткнулись на удивительное. Кодер скрыл отображение варнингов в VS2010. Метод М1 не всегда возвращал значение типа bool. И потому в методе М2, вызывающем метод М1,...
C++ Как средствами BC 3,1 запросить свободное место на указанном жёстком диске? http://www.cyberforum.ru/cpp/thread444851.html
Извиняюсь, если создал лишнюю тему, но ничего по своей проблемке я вроде не заметил. Если что-то есть, поправьте. А вопрос в следующем: как средствами BC 3,1 запросить свободное место на указанном...
C++ Указания адреса функции Есть библиотека. Нужно чтобы функция в моей библиотеке указывала на функцию в чужой. Вот мой код: typedef int (WINAPI WJMP)(); extern "C" __declspec(dllexport) WJMP Test(void); *Test=... подробнее

Показать сообщение отдельно
Evg
Эксперт CАвтор FAQ
18241 / 6366 / 435
Регистрация: 30.03.2009
Сообщений: 17,593
Записей в блоге: 28
17.02.2012, 12:53
Цитата Сообщение от AzaKendler Посмотреть сообщение
Evg, ну это понятно. тогда его вызов извне ограничен только в контексте языка с++ и концепции классов я прав?
и теоретически мы можем вызвать конструктор, поскольку он является обычной функцией найдя его адрес в загруженном в память файле. верно?
По поводу того, как читерскими способами (т.е. неязыковыми средствами) вызвать конструктор

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
 
class A
{
    int a;
  public:
    A (int);
};
 
void func (void)
{
}
 
A::A (int x) : a(55555555 + x)
{
}
 
long delta = 0;
 
int main (void)
{
  /* Читерская структура, которая соотвествует классу A */
  struct s
  {
    int x;
  };
 
  /* Читерская переменная, которую подсунем в конструктор в качестве
   * экземпляра класса A */
  struct s str;
  str.x = 0;
 
  /* Читерский прототип функции, который соответсвует конструктору A::A(int) */
  typedef void (*fptr_t) (struct s*, int);
 
  /* Адрес подставной функции func */
  long addr = (long) &func;
 
  /* Вычисляем адрес конструктора, предполагая, что компилятор расположит его
  * в памяти сразу после функции func */
  addr += delta;
 
  /* Читерским образом вызываем конструктор */
  ((fptr_t)addr) (&str, 1);
 
  /* для контроля проверим, что читерский объект действительно должным
   * образом проинициализирован */
  printf ("str.x=%d\n", str.x);
 
  return 0;
}
Мы здесь основываемся на том, что через адрес функции func мы сможем вычислить адрес конструктора (т.к. в памяти они будут лежать рядом по статическим адресам). Поскольку средствами языка нельзя взять адрес на конструктор, то мы это можем сделать, анализируя исполняемый файл. Пример я запускал на linux'е (оно покатит и на любом unix'е). Под виндой запускать ровно таким же образом, если кто-то знает, как там смотреть символьную таблицу исполняемого файла

Сначала делаем предварительный запуск с целью выяснения адреса

Код
$ g++ t.cc -fno-exceptions -O2
$ readelf --symbol a.out | grep FUNC
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
    44: 08048400     5 FUNC    GLOBAL DEFAULT   13 _Z4funcv
    47: 08048430    19 FUNC    GLOBAL DEFAULT   13 _ZN1AC1Ei
...
Метка _Z4funcv соответствует нашей функции func, метка _ZN1AC1Ei соответствует конструктору A::A(int). Во второй колонке написаны адреса этих функций (по научному Value). Вычисляем разницу адресов 0x08048430 - 0x08048400 = 0x30, а затем модифицируем программу, заменив "long delta = 0;" на "long delta = 0x30;". И далее запускаем:

Код
$ g++ t.cc -fno-exceptions -O2
$ ./a.out
str.x=55555556
Следует понимать, что в обоих случаях надо производить запуск компилятора с одними и теми же опциями, чтобы гарантировать одинаковость сгенерированного кода. В моём случае разница адресов получилась 0x30, но на каждой отдельной машине (на которой стоит своя версия компилятора) эта разница будет своя. Здесь я опираюсь на то, что компилятор gcc строит метод функции таким образом, как если бы эта была функция с скрытым первым параметром. Другие компиляторы, к пример, вправе поступать подругому, вправе изменять программные соглашения по передаче параметров в методы класса и т.п. Я здесь всего лишь показал, что технически это возможно, нужно только знать, как это делать

Добавлено через 2 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
или просто отдаст 3 регистра (будет сие означать выделение памяти)???
Будет. Строго говоря, вместо "выделение памяти" правильным будет назвать "выделение аппаратного ресурса", что есть память либо регистр. Но сточки зрения понимания вопроса это непринципиально. Людям удобнее оперировать понятием "память" и не заморачиваться тем, что ещё есть "регситр". В режиме без оптимизаций основная масса компиляторов все переменные складывает в память, и для экспериментов этого вполне достаточно
4
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru