sizeof struct为什么总是一个问题

在Win32 Crypto API里面很常用的一些接口如CryptImportKey, 会引入一些特定的数据结构作为key的内容和说明。我们在很多的sample里面看到了类似的定义,从而也发现了很诡谲的问题

struct KeyBLOB { BLOBHEADER header; DWORD cbKeySize; BYTE rgbKeyData[1]; };

应该说类似的定义在古老的win32代码里面随处可见,用一个byte来占个坑,但是后面接着的调用就发人深思了

memcpy(pbHash + sizeof(KeyBLOB) - 1, pSessionKey->pbData, pSessionKey->cbData);

为了方便起见,我们交代一下,pbHash是某个KeyBLOB实例的地址,我们略去了这里pSessionKey的类型说明,只是交代一下这里的pbData表示地址,cbData表示size。这样整个看似正确的代码就在product里面存在了。

但是这个代码是有问题的,问题在什么地方呢?就在这个-1上面。我们知道为了速度效率上的优化,我们C/C++里面的编译器对struct是做过alignment优化的。尽管这个KeyBLOB最后一个参数只有一个BYTE,但是实际上它还是占了4个byte,也就是说这个差别会出现在2个表达式里面:这个sizeof(KeyBLOB)-1和sizeof(BLOBHEADER)+sizeof(DWORD)不是同一个值。现在的我们的这个数据结构实际上变成了一个什么呢?

struct KeyBLOB { BLOBHEADER header; DWORD cbKeySize; BYTE zero[3]; BYTE rgbKeyData[1]; };

变成了这么一个东西,注意我们在这里添加了3个byte的数据,同时我们把这里变量故意命名成了zero以示提醒。当然这个只能是希望引起读代码的工程师的注意。

实际上这种情况在日常的开发过程中经常发生,个人觉得比较妥当的办法是避免使用这种所谓一个byte的数组。这种情况下面,实际上不会只是用到一个字节,通常这里需要的是一个完整的数组,现在的这个byte不过是来占坑的,既然如此我就干脆把需要的完整的数组定义出来。比如说我需要24Byte的,我就把这类的 rgbKeyData定义成[24]。如果说需要动态的长度不可预期,定义一个4的倍数的固定的长度也没有问题。因为可以往后面添加,而且已经是4的倍数就不会有alignment的问题。

你可能感兴趣的:(sizeof struct为什么总是一个问题)