如何检查 void* 指针是否可以安全地转换为其他内容?

发布于 2025-01-02 06:48:33 字数 616 浏览 3 评论 0原文

假设我有这个函数,它是某个 GUI 工具包的一部分:

typedef struct _My_Struct My_Struct;
/* struct ... */

void paint_handler( void* data )
{
   if ( IS_MY_STRUCT(data) ) /* <-- can I do something like this? */
   {
      My_Struct* str = (My_Struct*) data;
   }
}

/* in main() */
My_Struct s;
signal_connect( SIGNAL_PAINT, &paint_handler, (void*) &s ); /* sent s as a void* */

由于 Paint_handler 也将由 GUI 工具包的主循环​​使用其他参数调用,因此我不能总是确定我收到的参数将始终是指向 <代码>s。

我可以在 paint_handler 函数中执行类似 IS_MY_STRUCT 的操作来检查我收到的参数是否可以安全地转换回 My_Struct* 吗?

Let's say I have this function, which is part of some gui toolkit:

typedef struct _My_Struct My_Struct;
/* struct ... */

void paint_handler( void* data )
{
   if ( IS_MY_STRUCT(data) ) /* <-- can I do something like this? */
   {
      My_Struct* str = (My_Struct*) data;
   }
}

/* in main() */
My_Struct s;
signal_connect( SIGNAL_PAINT, &paint_handler, (void*) &s ); /* sent s as a void* */

Since the paint_handler will also be called by the GUI toolkit's main loop with other arguments, I cannot always be sure that the parameter I am receiving will always be a pointer to s.

Can I do something like IS_MY_STRUCT in the paint_handler function to check that the parameter I am receiving can be safely cast back to My_Struct* ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

別甾虛僞 2025-01-09 06:48:34

不幸的是,没有函数可以检查指针出现在该上下文中之前的内容(void)。

我能想到的一个解决方案是,如果您将 int _struct_id 作为所有结构的第一个成员。然后,无论类型如何,都可以安全地检查此 id 成员,但如果传递未实现此成员的指针(或 int、char、... 指针),则会失败。

Unfortunately there is no function to check what the pointer was before it appears in that context (void).

The one solution I can think of is if you place an int _struct_id as the first member of all of your structs. This id member can then be safely checked regardless of the type but this will fail if you pass pointers that don't implement this member (or int, char, ... pointers).

倾城泪 2025-01-09 06:48:34

你能做的最好的事情就是查看哪些数据点,看看它是否有迹象表明它是你想要的,尽管a)它不会接近保证,b)可能很危险,因为你不这样做不知道数据实际指向的东西有多大。我认为它并不比仅仅铸造和使用它更危险,但是(正如所建议的那样)重新设计会更好。

The best you could do would be to look at what data points to to see if it has telltale signs of being what you want, although a) it wouldn't be anywhere close to a guarantee and b) might be dangerous, as you don't know how big the thing data actually points to is. I suppose it isn't any more dangerous than just casting it and using it, but (as has been suggested) a redesign would be better.

忘东忘西忘不掉你 2025-01-09 06:48:34

如果您正在创建正在使用的类型,则可以包含某种标识信息作为类型的一部分,这些信息将帮助您排除某些不属于您正在查找的类型的空指针。虽然您可能会遇到某些随机内存区域包含与您正在查找的数据或签名相同的数据或签名的情况,但至少您会知道某些内容何时不是您正在查找的类型。

这种方法要求结构体以这样的方式初始化:用于确定内存区域是否无效的签名成员被初始化为签名值。

一个例子:

typedef struct {
    ULONG  ulSignature1;
    //  .. data elements that you want to have
    ULONG  ulSignature2;
} MySignedStruct;
#define MYSIGNEDSTRUCT_01  0x1F2E3D4C
#define MYSIGNEDSTRUCT_02  0xF1E2D3C4

#define IS_MY_STRUCT(sAdr)  ( (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_01  ) && (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_02))

这是一种粗略的方法,但它可以提供帮助。当然,如果参数有副作用,那么使用像 IS_MY_STRUCT() 这样的宏(其中参数使用两次)可能会出现问题,因此您必须小心像 IS_MY_STRUCT(xStruct++) 这样的宏code> 其中 xStruct 是指向 MySignedStruct 的指针。

If you are creating the type that is being used, you could include as part of the type some kind of identifying information that would help you rule out some void pointers as not being of the type you are looking for. While you would run the chance that some random area of memory would contain the same data or signature as what you are looking for, at least you would know when something was not the type you were looking for.

This approach would require that the struct was initialized in such a way that the signature members, used to determine if the memory area is not valid, is initialized to the signature value.

An example:

typedef struct {
    ULONG  ulSignature1;
    //  .. data elements that you want to have
    ULONG  ulSignature2;
} MySignedStruct;
#define MYSIGNEDSTRUCT_01  0x1F2E3D4C
#define MYSIGNEDSTRUCT_02  0xF1E2D3C4

#define IS_MY_STRUCT(sAdr)  ( (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_01  ) && (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_02))

This is kind of a rough approach however it can help. Naturally using a macro like IS_MY_STRUCT() where the argument is used twice can be problematic if the argument has a side effect so you would have to be careful of something like IS_MY_STRUCT(xStruct++) where xStruct is a pointer to a MySignedStruct.

情徒 2025-01-09 06:48:34

c中确实没有。 void 指针是无类型的,只有当您真正知道它们指向什么时才应该进行强制转换。

也许你应该重新考虑你的设计;重写您的代码,以便不需要检查。这与 Google 在其样式指南中不允许使用 RTTI 的原因相同。

There really isn't in c. void pointers are typeless, and should only ever be casted when you truly know what they point to.

Perhaps you should instead reconsider your design; rewrite your code so that no inspection is necessary. This is the same reason google disallows RTTI in its style guide.

天荒地未老 2025-01-09 06:48:34

我知道这个问题已经有 3 年历史了,但我来了,
如何使用一个简单的全局枚举来区分函数的调用位置。然后您可以在将 void 指针转换为哪种类型之间进行切换。

I know the question is 3 years old but here I go,
How about using a simple global enum to distinguish where the function is called from. then you can switch between what type to cast the void pointer to.

从﹋此江山别 2025-01-09 06:48:33

您的 void 指针会丢失其所有类型信息,因此仅凭这一点,您无法检查它是否可以安全地进行强制转换。由程序员决定是否可以将 void* 安全地转换为类型。

Your void pointer looses all its type information, so by that alone, you cannot check if it can be cast safely. It's up to the programmer to know if a void* can be cast safely to a type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文