什么是堆栈对齐?
为什么使用它?
可以通过编译器设置控制它吗?

这个问题的细节来自尝试将ffmpeg库与msvc一起使用时遇到的问题,但是我真正感兴趣的是对“堆栈对齐”的解释。

细节:

  • 当运行我的msvc编译程序并链接到avcodec时,我得到了
    出现以下错误:“编译器未对齐堆栈变量。Libavcodec具有
    被错误编译”,然后在avcodec.dll中崩溃。
  • avcodec.dll未使用msvc进行编译,因此我无法看到内部发生了什么。
  • 运行ffmpeg.exe并使用相同的avcodec.dll时,一切正常。
  • ffmpeg.exe并未使用msvc进行编译,而是使用gcc/mingw(与avcodec.dll相同)进行编译

  • 谢谢,

    最佳答案

    内存中变量的对齐(历史很短)。

    过去,计算机具有8位数据总线。这意味着,每个时钟周期可以处理8位信息。那很好。

    然后是16位计算机。由于向下兼容性和其他问题,保留了8位字节,并引入了16位字。每个字是2个字节。并且每个时钟周期可以处理16位信息。但这提出了一个小问题。

    让我们看一下内存映射:

    +----+
    |0000|
    |0001|
    +----+
    |0002|
    |0003|
    +----+
    |0004|
    |0005|
    +----+
    | .. |
    

    每个地址都有一个字节,可以单独访问。
    但是单词只能在偶数地址处获取。因此,如果我们在0000处读取一个字,则会在0000和0001处读取字节。但是,如果要在位置0001处读取该字,则需要两次读取访问。首先是0000,0001,然后是0002,0003,而我们仅保留0001,0002。

    当然,这花费了一些额外的时间,对此不胜感激。因此,这就是他们发明对齐技术的原因。因此,我们将字变量存储在字边界,将字节变量存储在字节边界。

    例如,如果我们有一个带有字节字段(B)和字字段(W)的结构(以及一个非常幼稚的编译器),则会得到以下内容:
    +----+
    |0000| B
    |0001| W
    +----+
    |0002| W
    |0003|
    +----+
    

    这不好玩。但是当使用单词对齐时,我们发现:
    +----+
    |0000| B
    |0001| -
    +----+
    |0002| W
    |0003| W
    +----+
    

    在此牺牲内存来提高访问速度。

    您可以想象,当使用双字(4个字节)或四字(8个字节)时,这甚至更为重要。这就是为什么对于大多数现代编译器,您可以在编译程序时选择要使用的对齐方式。

    07-27 21:42