Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как создать объект динамически, без использования new 
:(
    Опции темы
Чупакабро
Дата 15.10.2013, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: нет
Всего: 4



Есть код:
Код

pTerrains[x * 3 + y] = (Terrain*)GlobalAlloc(GHND, sizeof(Terrain));
*(pTerrains[x * 3 + y]) = Terrain::Terrain();
pTerrains[x * 3 + y]->Generate(&tp);

Третья строка выдает ошибку доступа к памяти.
Если объект создавать так:
Код

pTerrains[x * 3 + y] = new Terrain;

то все работает (кто бы сомневался).
Я вот понимаю, что для создания объекта недостаточно просто выделить под него память...
но что еще нужно-то сделать?
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
Чупакабро
Дата 15.10.2013, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: нет
Всего: 4



И тишина...
Где же вы, гении программистской мысли?
Проблема еще частично актуальна.
Методом тыка удалось выяснить, что сбой возникает только при вызове виртуальных функций.
Видимо, вся виртуальность идет прахом, когда не используется new, и программа не может получить фактический адрес функции.
ыыыыыыыыыыыыыыыы..... ладно, гутен морган, пора спать

Это сообщение отредактировал(а) Чупакабро - 15.10.2013, 23:42
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
feodorv
Дата 16.10.2013, 00:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Чупакабро @  16.10.2013,  00:41 Найти цитируемый пост)
И тишина...

Ну, загляните сюда на предмет Placement new...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Alexeis
Дата 16.10.2013, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 4
Всего: 459



Довольно любопытно почему таки падает. Единственное что приходит в голову это перегруженный оператор присваивания. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
vinter
Дата 16.10.2013, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Alexeis, падает потомучто UB во второй строчке: *(pTerrains[x * 3 + y]). Это есть разыменование невалидного указателя; всё, что идёт дальше значения не имеет. feodorv дал автору темы абсолютно верный ответ, который исчерпывает вопрос.

Это сообщение отредактировал(а) vinter - 16.10.2013, 09:43


--------------------
Мой блог
PM MAIL WWW   Вверх
Чупакабро
Дата 16.10.2013, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: нет
Всего: 4



Цитата(feodorv @  16.10.2013,  00:36 Найти цитируемый пост)
Ну, загляните сюда на предмет Placement new... 

Спасибо, почитал, но это немножко не то. Там рассказывается, как разместить объект по заранее известному адресу. Но у меня такой задачи нет. Задача в том, чтобы отказаться от использования рантайма студии (msvcrt.lib / msvcrt.dll) и, в частности, от new.

Цитата(Alexeis @  16.10.2013,  09:05 Найти цитируемый пост)
Довольно любопытно почему таки падает

В итоге, полазив по интернетам, нашел, в чем проблема.
Для каждого экземпляра класса с виртуальными функциями создается скрытый указатель на таблицу виртуальных функций. При том способе, который использую я, такого указателя не создается (или он создается, но туда записывается нулевой адрес).
В качестве решения нужно явно указывать версию используемой функции:
Код

pTerrains[x * 3 + y]->Terrain::Generate(&tp);


Добавлено через 3 минуты и 21 секунду
Цитата(vinter @  16.10.2013,  09:42 Найти цитируемый пост)
падает потомучто UB во второй строчке: *(pTerrains[x * 3 + y]).

Как же тогда правильно вызывать конструктор?
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
vinter
Дата 16.10.2013, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Код

pTerrains[x * 3 + y] = (Terrain*)GlobalAlloc(GHND, sizeof(Terrain));
new (pTerrains[x * 3 + y]) Terrain();
pTerrains[x * 3 + y]->Generate(&tp);

feodorv привёл правильные ссылки.

Это сообщение отредактировал(а) vinter - 16.10.2013, 09:55


--------------------
Мой блог
PM MAIL WWW   Вверх
Чупакабро
Дата 16.10.2013, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: нет
Всего: 4



Цитата(vinter @  16.10.2013,  09:54 Найти цитируемый пост)
feodorv привёл правильные ссылки.

Да чего тогда огород городить:
Код

pTerrains[x * 3 + y] = new Terrain;

Я бы так и сделал, но
мне нужно сделать создание объекта без использования new
как мне еще это выделить, чтобы заметили?

Это сообщение отредактировал(а) Чупакабро - 16.10.2013, 10:03
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
Alexeis
Дата 16.10.2013, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 4
Всего: 459



Цитата(Чупакабро @  16.10.2013,  10:45 Найти цитируемый пост)
В итоге, полазив по интернетам, нашел, в чем проблема.
Для каждого экземпляра класса с виртуальными функциями создается скрытый указатель на таблицу виртуальных функций. При том способе, который использую я, такого указателя не создается (или он создается, но туда записывается нулевой адрес).

  Возможно оператор копирования, не копирует адрес VMT. Вообще да, логично. Представим себе ситуацию что справа у нас объект не того же самого класса, а его наследник приведенный к нашему классу и разыменованный. В этом случае объект слева от знака равно получил бы указатель на VMT наследника, что несомненно является неверным поведением. Поэтому оператор копирования не трогает указатель на VMT и у объекта остается его родной не инициализированный указатель.
  Присоединяюсь к vinter и feodorv. Именно так следует действовать когда размещение объекта не стандартное.

Добавлено через 1 минуту и 58 секунд
Чупакабро, new это вызов конструктора + выделение памяти. Если выделение памяти заменить на свое, то new будет делать лишь вызов конструктора. Именно это и нужно сделать в данной ситуации. Ну или же самому записать указатель на VMT в объект. Это вполне реально если знать его смещение относительно начала объекта.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Чупакабро
Дата 16.10.2013, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: нет
Всего: 4



Цитата(Alexeis @  16.10.2013,  10:03 Найти цитируемый пост)
Ну или же самому записать указатель на VMT в объект. Это вполне реально если знать его смещение относительно начала объекта.

Ок, поэкспериментирую. По идее, там нулевое смещение, как я вычитал.
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
vinter
Дата 16.10.2013, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата

мне нужно сделать создание объекта без использования new

Это невозможно в C++. Используйте другой язык.


--------------------
Мой блог
PM MAIL WWW   Вверх
feodorv
Дата 16.10.2013, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Сначала:
Цитата(Чупакабро @  15.10.2013,  20:59 Найти цитируемый пост)
Я вот понимаю, что для создания объекта недостаточно просто выделить под него память...
но что еще нужно-то сделать? 

Потом:
Цитата(Чупакабро @  16.10.2013,  10:45 Найти цитируемый пост)
Там рассказывается, как разместить объект по заранее известному адресу. Но у меня такой задачи нет. Задача в том, чтобы отказаться от использования рантайма студии (msvcrt.lib / msvcrt.dll) и, в частности, от new.

Тогда не используйте сложных класов, переходите на структуры, инициализируйте их явным образом, вместо виртуальных функций используйте указатели на функции, и, да, переходите на C  smile 

Чем Вам msvcrt.lib / msvcrt.dll насолили? И, гм, разве try/catch не в рантайме?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Alexeis
Дата 16.10.2013, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 4
Всего: 459



Цитата(Чупакабро @  16.10.2013,  11:15 Найти цитируемый пост)
Ок, поэкспериментирую. По идее, там нулевое смещение, как я вычитал. 

  В этом конкретном объекте может. На самом деле зависит от иерархии объектов. Если первый же предок имеет VMT то первая VMT будет первым полем. При множественном наследовании будет несколько таблиц VMT и они будут размещены с различными смещениями.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Чупакабро
Дата 16.10.2013, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: нет
Всего: 4



Цитата(vinter @  16.10.2013,  10:19 Найти цитируемый пост)
Это невозможно в C++.

эээ... даже не знаю, что на это сказать))

Цитата(feodorv @  16.10.2013,  10:45 Найти цитируемый пост)
Чем Вам msvcrt.lib / msvcrt.dll насолили? И, гм, разве try/catch не в рантайме? 

error LNK: Cannot find symbol '___CxxFrameHandler3'
походу в рантайме
рантайм насолил тем, что нужно а) обеспечить запуск приложения на чистой системе, в которой может не быть msvcrtXX от моей студии (поэтому отказываемся от dll),  б) минимизировать размер приложения (поэтому отказываемся от статической линковки).

Цитата(feodorv @  16.10.2013,  10:45 Найти цитируемый пост)
Тогда не используйте сложных класов, переходите на структуры, инициализируйте их явным образом, вместо виртуальных функций используйте указатели на функции, и, да, переходите на C

В данной конкретной программе от виртуальных функций наверное откажусь. Хотя, как я понимаю, проблема с ними решаема.
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
vinter
Дата 16.10.2013, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



а если добавить виртуальное наследование, то становится еще веселее. И не забываем, что размещение всего, что касается типов отличных от standard layout не детерминировано, сиречь может изменится в любой версии любого компилятора.


--------------------
Мой блог
PM MAIL WWW   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0612 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.