我第一次开始在Windows上使用SetupAPI,并注意到在调用填充该结构的函数之前,我总是需要将结构的大小放入结构中。例如:
SP_DEVICE_INTERFACE_DATA dintf_data;
dintf_data.cbSize = sizeof(dintf_data);
SetupDiEnumDeviceInterfaces(di, NULL, &GUID_DEVINTERFACE_USB_DEVICE, 0, &dintf_data);
为什么要这么做?
这是一个很好的方式来实现它是他们正在努力实现,还是有更好的方法?
(我能想到的唯一原因是它是处理API版本控制的一种方法。)
发布于 2014-09-18 07:05:40
是的,你明白了,API版本控制。
操作系统检查传入的大小,以确定正在使用的结构的哪个版本。在为API的新版本添加功能时,会添加字段(永不移除),以增加大小,这样操作系统就可以很容易地知道您使用的是哪个版本。
发布于 2014-09-18 07:17:38
这是一种版本控制方式,以确保向后(和向前!)兼容性。
想象一下,您有一些用于消息框的struct
:
struct MessageBoxData {
const char *message;
const char *caption;
};
您可以将其编译到API中,并使用它显示带有message
和caption
的消息框。你很好。
稍后,发布API版本2,它为显示的图标添加了另一个字段:
struct MessageBoxData {
const char *message;
const char *caption;
unsigned char icon;
};
让我们假设元素的顺序不是由编译器神奇地填充或重组的,而且任何程序都可以将这个更复杂的API版本2结构传递给API版本1库,而不会出现问题。
然而,反过来又会发生什么呢?使用针对API版本1编译的程序和API版本2的库。
库将尝试读取icon
,这将导致在此struct
的有效边界之外读取!
例如,如果尝试使用memcpy()
复制内容,可能会以类似的方式出现问题。
为了避免这种情况,Windows通常期望第一个成员定义结构的实际大小。在本例中,您可以创建如下所示:
// Version 1
struct MessageBoxData {
unsigned int size;
const char *message;
const char *caption;
};
// Version 2
struct MessageBoxData {
unsigned int size;
const char *message;
const char *caption;
unsigned char icon;
};
您可能认为他们可以只在被调用的函数中使用sizeof()
。虽然这在理论上是正确的,但它不能解决编译时(库和程序)之间的不同定义的问题。
https://stackoverflow.com/questions/25906251
复制相似问题