【问题标题】:Find pointer/class using raw memory address使用原始内存地址查找指针/类
【发布时间】:2012-05-01 12:21:02
【问题描述】:

在我问我的问题之前,我想说我意识到有一些“类似”的问题,但没有(我能找到)专门回答我的问题,所以就这样吧。

我想知道以下是否可能。假设我创建了一个类的 new 实例,如下所示:

MyClass* classInstance = new MyClass();

我想知道是否可以将原始内存地址存储为原始类型,例如 int。然后,在 C++ no-mans-land 的某个地方,我没有指向 classInstance 的指针,我可以这样做:

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

如果有可能,是否有任何风险?这样的事情是否有任何重大的开销成本?我意识到这个设计很糟糕,但不幸的是我受制于third party here。所以请不要为此责备我,但请随时chastise them。 :)

对这种疯狂的解释
所以只是为了进一步解释为什么我必须做一些像这样愚蠢的事情。我正在将 box2D 移植到 AIR 本机扩展,正如我之前提到的,我受制于 AIR 运行时。它处理本机端和 Actionscript 端之间关联的方式是......搞砸了,而且还有很多荒谬的规则来进行这种关联。

这样的规则对于像b2World->createBody() 这样的情况会产生真正的问题,它返回一个指向b2Body 类型(它有一个私有构造函数)的指针。在此关联期间,我无法同时创建一个上下文以将新的b2Body 指针与其关联,因为在此调用期间,我被困在b2World 的上下文中。因此,与其在b2Worldb2Body 这样的类中将一堆肮脏的hacks 一起拍打,我想知道我是否可以使用像int 这样的原始类型来存储和返回新b2Body 的内存地址。

我无法将从 C++ 键入的指针或结构返回到 Actionscript 端。我只能与上下文关联......但我可以返回原始类型。

【问题讨论】:

  • 唯一的风险是转换为错误的类类型或转换为释放指针。没有开销,只需静态转换网络类指针。
  • 所以我的代码可以正常工作吗?将地址存储在什么类型的对象中然后重新调用它是安全的?
  • 我认为您尝试做的事情违反了严格的指针别名规则。
  • 这和指针有什么区别?您只想将其存储在通用内存中吗?以后你将如何识别类型?
  • 有可能。不过,通常不建议提供这样的原始内存地址。但我真的不明白指针有什么好处。

标签: c++ air-native-extension


【解决方案1】:

到目前为止,最简单的解决方案是std::map<unsigned int, MyClass*>。几乎唯一的缺点是,在UINT_MAX 分配之后,您将不得不去寻找可重用的值。

【讨论】:

  • 我也想到了这一点,如果我的问题中的想法真的不可行,这就是我的默认设置。
【解决方案2】:

许多第三方 api 会强制您使用这种类型的模式来传递数据。您将遇到的唯一问题是,如果您像建议的那样使用 int 的原始类型,那么如果您曾经为 64 位平台编译,那么此代码将不可移植,因为原始类型 int 不会保存可用的最大地址在 64 位平台上。您可以使用内置类型 int_ptr,当编译为 32 位平台时为 32 位,而为 64 位平台编译时为 64 位以避免此问题,或者您可以使用 void* 作为原始类型,如 win32 CreateThread 函数或 pthread_create 函数。

【讨论】:

    【解决方案3】:

    您是否考虑过标记这个“AIR 原生扩展”以及 C++?需要注意的是,我既不知道 box2d 也不知道 AIR Native Extension,这让我感到震惊,您可能正在尝试做其他人以前尝试过的事情,并且可能是 Adob​​e 不希望您做的事情 - 可能有充分的理由。例如:

    我无法将 C++ 类型的指针或结构返回给 动作脚本方面。我只能与上下文相关联......但我可以 返回原始类型

    您是否真的可以在 Actionscript 中使用指针,还是仅将其保留为原始类型,以便将其传递回接口?

    也许在这种情况下,您可以将指针存储在一个关联集合(如地图)中,并将键作为句柄返回。当您将句柄传回时,C++ 端可以查找指针并根据上下文进行适当的转换。这样一来,您永远不会通过接口本身传递指针,因此您不会受到任何与指针相关的问题的影响。

    如果您已经在考虑这些问题,我们深表歉意。

    【讨论】:

    • 我并不是说听起来粗鲁,但 AIR Native Extensions 是相当新的东西,最感兴趣的人是纯粹的 Flash 开发人员。再次不是听起来粗鲁的意思,但是......一个试图进入这个世界的 Flash 开发人员......好吧,我在一年前就做到了,我仍然是 C++ 的婴儿,哈哈。大多数本地扩展都写成完全错误。我已经阅读了完整的 100 多页文档,后来意识到从现有的扩展中没有什么可收集的除了如何做错。
    • 所以我没有标记它。另外,是的,我已经考虑过映射,但想避免必须进行查找,因为应用程序的性能已经被 AIR 运行时拖累了,所以每一点都有帮助。但这似乎是唯一可行(安全)的解决方案。最后要回答关于使用带有动作脚本的指针的问题,我只能通过将本机动作脚本上下文与本机指针相关联并通过特殊结构化的接口来做到这一点。所有的互动都是间接的。
    • @Ascension Systems:没有冒犯。通常有充分的理由限制来自 API 的机器特定细节,这些 API 允许从机器独立语言连接到本机代码,并且正如您所见,它们通常很难解决。尽量将您的模型复杂性保持在本机代码中,并尽可能避免通过扩展暴露太多。与 AIR 所做的相比,映射可能对性能的影响最小。您可以尝试使用稀疏向量,其中您的 handle 是向量的索引 - 这应该是相当理想的。
    【解决方案4】:

    要转换的适当值是intptr_tuintptr_t,但我认为Adobe 没有这些...

    所以把 C++ 的可移植性放在一边,只是为了实用,如果你在 32 位架构中,那么 unsigned int 应该没问题,在 64 位中,unsigned long,这是一个足够长的整数保存指针的值。 unsigned 部分只是为了安全起见,但你应该也可以不使用它。

    您必须注意的主要事项是从整数类型转换为整数类型的指针类型必须相同。也就是说,以下是未定义的行为:

    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));
    

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 1970-01-01
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      相关资源
      最近更新 更多