Найти указатель/класс, используя необработанный адрес памяти

Прежде чем я задам свой вопрос, я хочу сказать, что понимаю, что есть некоторые «похожие» вопросы, но ничего (что я могу найти), что конкретно отвечает на мой вопрос, так что вот.

Мне интересно, возможно ли следующее. Допустим, я создаю new экземпляр класса, например:

MyClass* classInstance = new MyClass();

Мне интересно, можно ли сохранить необработанный адрес памяти, скажем, в примитивном типе, таком как int. Затем где-то в ничейной зоне С++, где у меня нет указателя на classInstance, я могу сделать что-то вроде этого:

MyClass* myClassInstanceSomewhereInMemory = (MyClass*)0x12345678;
myClassInstanceSomewhereInMemory->workPlzKThx(); //Yay, it works!

В случае, если это возможно, существуют ли какие-либо риски? Существуют ли какие-либо значительные накладные расходы для такой вещи? Я понимаю, что это довольно плохой дизайн, но, к сожалению, здесь я отдан на милость третьей стороне. Поэтому, пожалуйста, не ругайте меня за это, а накажите их . :)

Объяснение этого безумия
Итак, просто чтобы объяснить немного больше, почему я должен делать что-то настолько глупое, как это. Я переношу box2D в собственное расширение AIR, и, как я упоминал ранее, я нахожусь во власти среды выполнения AIR. То, как он обрабатывает связь между нативной стороной и стороной Actionscript,... запутано, и, кроме того, существует множество нелепых правил для этой ассоциации.

Одно такое правило создает настоящую проблему для таких ситуаций, как b2World->createBody(), которое возвращает указатель на тип b2Body (у которого есть закрытый конструктор). Во время этой ассоциации я не могу одновременно создать контекст, чтобы связать с ним новый указатель b2Body, потому что во время этого вызова я застрял в контексте b2World. Поэтому вместо того, чтобы собирать кучу грязных хаков в классах, таких как b2World и b2Body, мне интересно, могу ли я просто использовать примитивный тип, такой как int, для хранения и возврата адреса памяти нового b2Body.

Я не могу вернуть указатель или структуру, набранную из C++, обратно на сторону ActionScript. Я могу ассоциироваться только с контекстами... но я могу возвращать примитивные типы.


person Community    schedule 01.05.2012    source источник
comment
Единственный риск заключается в приведении к неправильному типу класса или освобождению указателя приведения. Никаких накладных расходов, а только статические указатели класса netween.   -  person Denis Ermolin    schedule 01.05.2012
comment
Итак, мой код, как он будет работать? В каком типе объекта было бы безопасно сохранить адрес, а затем повторно вызвать его?   -  person    schedule 01.05.2012
comment
Я думаю, что то, что вы пытаетесь сделать, нарушает строгие правила псевдонима указателя.   -  person Tony The Lion    schedule 01.05.2012
comment
В чем разница между этим и указателем? Вы хотите сохранить его только в общей памяти? Как вы собираетесь идентифицировать тип позже?   -  person Component 10    schedule 01.05.2012
comment
Это возможно. Однако обычно не рекомендуется давать такие необработанные адреса памяти. Но я действительно не понимаю, в чем преимущества над указателем.   -  person Morwenn    schedule 01.05.2012
comment
Если вы хотите хранить указатели любого типа, используйте boost::any   -  person Denis Ermolin    schedule 01.05.2012
comment
@Morwenn Я обновлю свой вопрос, чтобы объяснить ситуацию.   -  person    schedule 01.05.2012
comment
@ Component10 Я обновил свой ответ, чтобы объяснить дальше. У меня не будет возможности перепутать тип, когда я иду к повторному броску, указывая обратно на адрес. Дизайн приложения будет таким, что этого никогда не произойдет.   -  person    schedule 01.05.2012
comment
возможный дубликат как присвоить адрес указателю, где адрес хранится в объекте CString?   -  person    schedule 01.05.2012


Ответы (4)


Безусловно, самым простым решением является std::map<unsigned int, MyClass*>. Практически единственный недостаток заключается в том, что после UINT_MAX аллокации вам придется искать повторно используемые значения.

person MSalters    schedule 01.05.2012
comment
Я тоже об этом думал, и это то, к чему я собирался по умолчанию, если идея в моем вопросе действительно невыполнима. - person ; 01.05.2012

Многие сторонние API заставят вас использовать этот тип шаблона для передачи данных. Единственная проблема, которая у вас возникнет, заключается в том, что если вы используете примитивный тип int, как вы предложили, то, если вы когда-нибудь скомпилируете для 64-битной платформы, тогда этот код не будет переносимым, поскольку примитивный тип int не будет содержать максимально доступный адрес на 64-битной платформе. Вы можете использовать встроенный тип int_ptr, который при компиляции для 32-битных платформ является 32-битным, а для 64-битных платформ — 64-битным, чтобы избежать этой проблемы, или вы можете использовать void* в качестве примитивного типа, такого как функция Win32 CreateThread или функция pthread_create.

person user1359278    schedule 01.05.2012

Думали ли вы пометить это «AIR Native Extension» так же, как и C++? С оговоркой, что я не знаю ни box2d, ни AIR Native Extension, мне кажется, что вы, вероятно, пытаетесь сделать что-то, что другие пытались сделать раньше, и, возможно, что-то, что Adobe предпочитает, чтобы вы не делали - возможно, по уважительной причине. Например:

Я не могу вернуть указатель или структуру, набранную из C++, обратно на сторону ActionScript. Я могу ассоциироваться только с контекстами... но я могу возвращать примитивные типы

Могли бы вы на самом деле использовать указатель в ActionScript или вы просто сохраняете его в примитивном типе, чтобы вы могли передать его обратно в интерфейс?

Возможно, в этом случае вы могли бы сохранить указатель в ассоциативной коллекции, такой как карта, и вернуть ключ как дескриптор. Когда вы передаете дескриптор обратно, сторона C++ может искать указатель и выполнять приведение к соответствующему контексту. Таким образом, вы никогда не будете передавать указатель как таковой через интерфейс, поэтому вы не будете уязвимы для любых проблем, связанных с указателем.

Извините, если вы уже думали об этих строках.

person Component 10    schedule 01.05.2012
comment
Я не хочу показаться грубым, но AIR Native Extensions довольно новы, и люди, в основном заинтересованные в них, являются чисто разработчиками флэш-памяти. Опять же, не хочу показаться грубым, но... флеш-разработчик пытается прийти в этот мир... ну, я сделал это более года назад, и я все еще ребенок в C++, лол. Большинство нативных расширений были написаны совершенно неправильно. Я прочитал более 100 страниц документации по нему и впоследствии понял, что из существующих расширений нечего почерпнуть, кроме того, как сделать это неправильно. - person ; 01.05.2012
comment
Вот поэтому я и не поставил тег. Кроме того, да, я уже думал о сопоставлении, но хотел избежать необходимости выполнять поиск, потому что производительность приложения уже достаточно снижена во время выполнения AIR, поэтому каждая мелочь помогает. Но кажется, что это может быть единственным жизнеспособным (безопасным) решением. И, наконец, чтобы ответить на вопрос об использовании указателя со скриптом действия, я могу сделать это только путем связывания собственного контекста сценария действия с собственным указателем и через специально структурированные интерфейсы. Все взаимодействия косвенные. - person ; 01.05.2012
comment
@Ascension Systems: Без обид. Обычно есть веские причины для ограничения деталей, специфичных для машины, из API-интерфейсов, которые позволяют подключать независимые от машины языки к собственному коду, и, как вы видели, их часто сложно обойти. Постарайтесь сохранить сложность вашей модели в собственном коде и, если возможно, не раскрывайте слишком много через расширение. Отображение, вероятно, окажет минимальное влияние на производительность по сравнению с тем, что делает AIR. Вы можете попробовать использовать разреженные векторы, где ваш дескриптор является индексом в векторе - это должно быть достаточно оптимальным. - person Component 10; 01.05.2012

Подходящим значением для приведения является intptr_t или uintptr_t, но я не думаю, что у Adobe есть такие...

Итак, если оставить в стороне переносимость С++ и просто быть практичным, если вы работаете в 32-битной архитектуре, то unsigned int должно быть хорошо, а в 64-битной unsigned long, это целое число, достаточно длинное, чтобы содержать значение указателя . Часть unsigned предназначена только для перестраховки, но вы также можете играть без нее.

Главное, что вы должны знать, это то, что типы указателей, преобразованные из целочисленного типа и в него, должны быть идентичными. То есть следующее поведение undefined:

class  A {  };
class B : public A {};

B b;
A *pa = &b;
unsigned x = reinterpret_cast<unsigned>(&a);
B *pb = reinterpret_cast<B*>(x); //UB!

Последняя строка должна быть:

A *pb = reinterpret_cast<A*>(x);

Или еще:

B *pb = static_cast<B*>(reinterpret_cast<A*>(x));
person rodrigo    schedule 01.05.2012