检查不透明的C手柄是否正常

时间:2014-01-23 21:45:34

标签: c++ c api wrapper

我有一个带有C包装器的C ++ API。 C客户端可以获取底层C ++对象的句柄,然后使用它来获取有关该对象的其他信息,例如

PersonHandle handle = createPerson("NisseIHult");
char* name = getPersonName(handle); //Get person takes a void* pointer

在上面的代码中,句柄被转换为C ++ Person类对象。

问题是,如何检查getPersonName里面的参数handle是一个有效的句柄?例如,如果客户端执行此操作:

char * name = getPersonName(1234);

它将导致getPersonName中的访问冲突。我需要一种检查和验证句柄的方法,在上面的例子中,返回NULL?

2 个答案:

答案 0 :(得分:3)

由于句柄是指向C ++对象的指针,因此没有可靠的方法来检查它们的有效性而不会触发一些未定义的行为。

我已经看到了解决这个问题的两种方法:

  • 使句柄整数可以完全控制 - 而不是发出指针,在内部保留指针 - 例如,在从int到指针的无序映射中,以及一些元数据,并给出用户整数用作句柄。这在访问人员的过程中引入了额外的哈希查找,但您可以使其完全可靠,因为所有int都在您的控制之下。例如,如果您为不同类型的对象提供句柄,则可以生成详细的错误消息,例如“在需要Horse句柄的地方使用了Person对象的句柄”。此解决方案还有一个额外的优点,即您没有悬空引用:用户可以传递您已失效的句柄,但您可以快速判断该对象已被删除。
  • 从公共基类派生您提供句柄的所有对象,并将“幻数”放入该类的第一个成员 - “幻数”是您的位模式比如说放在int中,并在每个Person对象中设置它。演员表演结束后,您可以查看if (personFromHandle->magic != 0xBEEFBEEF) ...以查看该模式是否存在。这个解决方案很常见,但我建议不要这样做,因为它在传递无效句柄时有不确定的行为。如果在尝试使用句柄失败后继续操作,则不能使用它。如果传递对已释放对象的引用,此解决方案也会中断。

答案 1 :(得分:1)

与上面答案的第一部分类似,将您分发的每个对象的地址放入std::set(或类似的容器)中,并在投射前测试set中是否存在。