为什么结构的 sizeof 是不安全的 [英] Why sizeof of a struct is unsafe

查看:43
本文介绍了为什么结构的 sizeof 是不安全的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MSDN 明确说明

对于所有其他类型,包括结构体,sizeof 运算符只能用于不安全的代码块.

For all other types, including structs, the sizeof operator can only be used in unsafe code blocks.

C# 语言规范更加精确:

  1. 未指定成员打包到结构中的顺序.
  2. 出于对齐的目的,开头可能会有未命名的填充结构的、结构内的和结构的末尾.
  3. 用作填充的位的内容是不确定的.
  4. 当应用于具有 struct 类型的操作数时,结果是该类型变量中的总字节数,包括任何填充.

但是,CLR 将如何处理以下结构:

However how would the CLR handle the following structures :

[StructLayout(LayoutKind.Explicit, Size = 1, Pack = 1)]
public struct MyStruct
{
    [FieldOffset(0)] public byte aByte;
}

public struct MyEmptyStruct { }

MyStruct 中,我们通过 StructLayout 属性明确地强制布局、大小以及如何打包.该结构应该在内存中的大小为 1 个字节.

In MyStruct we enforce the layout explicitly, the size and how to pack it via the StructLayout attribute. This structure is supposed to have a size of 1 byte in memory.

另一方面 MyEmptyStruct 是空的,我们可以假设内存中的大小为 0 字节 - 即使这样的结构很可能不会被使用,它仍然是一个有趣的例子.

On the other hand MyEmptyStruct is empty, we can assume that the size in memory will be 0 bytes - even if a such structure is most likely not going to be used it still is an interesting case.

当尝试使用 sizeof(MyStruct)sizeof(MyEmptyStruct) 计算这些结构的大小时,编译器抛出以下错误:

When trying to compute the size of theses structures using sizeof(MyStruct) and sizeof(MyEmptyStruct) the compiler throws the following error :

'*' 没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用

'*' does not have a predefined size, therefore sizeof can only be used in an unsafe context

我想知道为什么在这种情况下使用 sizeof 被认为是不安全的.这个问题的目的不是寻求解决方法,也不是正确计算结构大小的方法,而是关注原因.

I would like to know why using sizeof in this context is considered unsafe. The question is not intended to ask for workarounds nor the correct way to compute the size of a struct but rather to focus on the causes.

推荐答案

我想知道为什么在这种情况下使用 sizeof 被认为是不安全的.

I would like to know why using sizeof in this context is considered unsafe.

Matthew Watson 的评论一针见血.你打算如何处理安全代码中的这些信息?它对任何事情都没有用(*).它不会告诉您需要分配多少非托管字节给 marshal;那是 Marshal.SizeOf.只对指针运算有用,为什么要放在安全子集中​​呢?

Matthew Watson's comment hits the nail on the head. What are you going to do with that information in safe code? It's not useful for anything(*). It doesn't tell you how many unmanaged bytes you need to allocate to marshal; that's Marshal.SizeOf. It's only useful for pointer arithmetic, so why should it be in the safe subset?

(*) 公平地说,安全 sizeof 有一些奇怪的极端情况用法,可以采用包含托管类型的结构.例如,假设您有一个通用集合类,它将分配一堆数组,并希望确保这些数组不会移动到大对象堆中;如果您可以获取包含托管对象的结构的大小,那么您可以非常轻松地编写此代码,并且不需要任何指针算法.但事实仍然是 sizeof 是专门为指针算术设计的,而不是为了让您可以对数组的垃圾收集启发式进行最终运行.

(*) OK to be fair there are a few odd corner case usages for a safe sizeof that can take structs that contain managed types. Suppose for example you have a generic collection class that is going to allocate a bunch of arrays and would like to ensure that those arrays are not moved into the large object heap; if you could take the size of a struct that contained managed objects then you could write this code very easily, and it would not need any pointer arithmetic. But the fact remains that sizeof was designed specifically for pointer arithmetic, and not so that you could do an end-run around the garbage collection heuristics for arrays.

这篇关于为什么结构的 sizeof 是不安全的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆