首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >导致溢出的二进制整数操作有可能覆盖相邻内存吗?

导致溢出的二进制整数操作有可能覆盖相邻内存吗?
EN

Stack Overflow用户
提问于 2011-02-24 18:19:24
回答 3查看 258关注 0票数 1

这个问题与我目前所看到的任何错误无关,它更多的是关于理论和对HW架构设计和实现中的变化的了解。

场景1:假设16位处理器具有16位寄存器、16位寻址和sizeof(int) =16位:

代码语言:javascript
复制
unsigned int a, b, c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

是否有可能覆盖c旁边的内存位置?

(在这种情况下,我预计在添加操作期间会出现溢出标志,c要么保持不变,要么被未定义的数据填充。)

场景2:假设32位处理器具有32位寄存器、32位寻址、sizeof(int) =32位和sizeof(短int)=16位:

代码语言:javascript
复制
unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

是否有可能覆盖c旁边的内存位置?

(我预计在add操作期间不会升起溢出标志,但在分配操作期间是否升起内存访问或溢出标志将取决于HW的实际设计和实现。如果d位于同一32位地址位置的上16位(使用32位地址可能甚至不可能),那么它可能会被覆盖。

场景3:假设具有32位寄存器的32位处理器、16-bit寻址、sizeof(int) =32位和sizeof(短int)=16位:

代码语言:javascript
复制
unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;

是否有可能覆盖c旁边的内存位置?

(我希望在类型转换和赋值操作期间会出现一些溢出标志或内存冲突标志。)

场景4:假设32位处理器具有32位寄存器、32位寻址和sizeof(int) =32位:

代码语言:javascript
复制
unsigned int a, b;
struct {
    unsigned int c:16;
    unsigned int d:16;
} e;
a=0xFFFF;
b=0xFFFF;
e.c=a+b;

是否有可能覆盖c旁边的内存位置,即d?(在这种情况下,由于cd应该驻留在相同的32位地址中,而且在技术上都是32位整数,因此可以想象在加法或赋值期间不会出现溢出标志,d可能会受到影响。)

我没有尝试在实际的硬件上测试这一点,因为我的问题更多的是关于设计和实现中的理论和可能的变化。任何洞察力都将不胜感激。

  • 导致溢出的二进制整数操作有可能覆盖相邻内存吗?
  • 目前是否有任何HW实现遇到类似的内存覆盖问题,或者过去是否有系统存在此问题?
  • 典型的处理器使用哪些设备来防止相邻内存被算术和赋值操作覆盖?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-02-24 18:33:15

加法操作是在处理器afaik中处理的,因此无论您做什么,添加操作都将在CPU内完成(在ALU中更准确地说)溢出寄存器将在溢出的情况下被设置,结果将仍然在寄存器中,然后复制回您的内存位置而不会破坏相邻的内存。这就是如何将代码(某种程度上)翻译成asm:

代码语言:javascript
复制
mov ax, ptr [memory location of a]
mov bx, ptr [memory location of b]
add ax,bx
mov ptr [memory location of c], ax

因此,正如您所看到的,无论是否发生溢出,c只保留ax中的内容(它的大小是已知的和固定的)。

票数 1
EN

Stack Overflow用户

发布于 2011-02-24 18:28:27

您的1,2,3,4将不会导致任何内存损坏,或写入“过去”存储的整数位置,您正在执行算术。C指定在无符号整数溢出时应发生什么情况。这是假设编译器生成它应该生成的代码。没有什么可以保护您,这是一个错误的编译器,它生成将4个字节复制到一个2字节变量中的代码。

下面是C99 (6.2.5)所说的话:

“涉及无符号操作数的计算永远不能在flow上进行,因为不能用结果无符号整数类型表示的结果被减少为模,即大于可以由结果类型表示的最大值的数。”

因此,当您试图“溢出”一个无符号整数时,会发生什么,这是非常明确的。

现在,如果你的整数是有符号整数,那就另当别论了。根据C,溢出有符号整数会导致未定义的行为。而未定义的行为意味着任何事情,包括内存损坏,都可能发生。不过,我还没有见过一个C编译器会破坏任何关于溢出整数的东西。

典型的处理器使用哪些设备来防止相邻内存被算术和赋值操作覆盖?

在分配和算术操作方面没有防止相邻内存的保护措施。处理器只执行给它的机器代码指令(如果这些指令覆盖内存,它就不会像用高级语言表示的那样那样做,处理器就不关心了)。

在稍微不同的级别上,如果CPU不能执行操作(例如,不存在的操作指定的内存位置),或者尝试执行一些非法操作(例如,除以零,或者遇到处理器不理解的op代码,或者尝试对数据进行非对齐访问),则CPU可能会发出陷阱

票数 4
EN

Stack Overflow用户

发布于 2011-02-24 18:47:28

在C语言中,无符号类型溢出的行为定义得很好.任何溢出导致除标准预测之外的任何结果都是不符合的实现。

带符号类型的溢出行为未定义。虽然溢出的最常见影响可能是分配某些错误的值或彻底崩溃,但C标准中没有任何东西保证处理器不会以编译后的代码试图恢复的方式触发溢出错误,但由于某种原因,它会破坏堆栈变量或寄存器的内容。也有可能溢出会导致标记以代码所不期望的方式设置,并且这样的标志可能会在未来的计算中导致错误的行为。

其他语言在发生溢出时可能有不同的语义。

注意:我看到了捕获溢出的处理器、与外部中断同时发生的意外陷阱可能导致数据损坏的处理器,以及意外的无符号溢出可能导致后续计算中断的处理器。我不知道有符号溢出会在哪里锁定会干扰后续计算的标志,但是有些DSP有有趣的溢出行为,所以如果存在溢出,我就不会感到惊讶。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5108766

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档