Форум программистов, компьютерный форум CyberForum.ru

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

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

Показать сообщение отдельно
Evg
Эксперт CАвтор FAQ
17411 / 5649 / 355
Регистрация: 30.03.2009
Сообщений: 15,467
Записей в блоге: 26
17.02.2012, 12:53     [C++] Взятие адреса конструктора. Физическое время существование объекта.
Цитата Сообщение от 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 регистра (будет сие означать выделение памяти)???
Будет. Строго говоря, вместо "выделение памяти" правильным будет назвать "выделение аппаратного ресурса", что есть память либо регистр. Но сточки зрения понимания вопроса это непринципиально. Людям удобнее оперировать понятием "память" и не заморачиваться тем, что ещё есть "регситр". В режиме без оптимизаций основная масса компиляторов все переменные складывает в память, и для экспериментов этого вполне достаточно
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru