Memory leaks 导致溢出的二进制整数操作是否可能覆盖相邻内存?

Memory leaks 导致溢出的二进制整数操作是否可能覆盖相邻内存?,memory-leaks,theory,overflow,cpu-architecture,Memory Leaks,Theory,Overflow,Cpu Architecture,这个问题与我目前看到的任何错误无关,更多的是关于理论,以及在硬件架构设计和实现方面的变化。 场景1:假设16位处理器具有16位寄存器、16位寻址和sizeofint=16位: unsigned int a, b, c, d; a=0xFFFF; b=0xFFFF; c=a+b; 是否有可能覆盖c旁边的内存位置?在这种情况下,我希望在add操作期间会出现溢出标志,而c要么保持不变,要么用未定义的数据填充。 场景2:假设32位处理器具有32位寄存器、32位寻址、sizeofint=32位和size

这个问题与我目前看到的任何错误无关,更多的是关于理论,以及在硬件架构设计和实现方面的变化。 场景1:假设16位处理器具有16位寄存器、16位寻址和sizeofint=16位:

unsigned int a, b, c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;
是否有可能覆盖c旁边的内存位置?在这种情况下,我希望在add操作期间会出现溢出标志,而c要么保持不变,要么用未定义的数据填充。 场景2:假设32位处理器具有32位寄存器、32位寻址、sizeofint=32位和sizeofshort int=16位:

unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;
unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;
是否有可能覆盖c旁边的内存位置?我希望在添加操作期间不会出现溢出标志,但在分配操作期间是否出现内存访问或溢出标志将取决于硬件的实际设计和实现。如果d位于同一32位地址位置的上16位,则可能无法使用32位寻址,它可能会被覆盖。 场景3:假设32位处理器具有32位寄存器、16位寻址、sizeofint=32位和sizeofshort int=16位:

unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;
unsigned int a, b;
unsigned short int c, d;
a=0xFFFF;
b=0xFFFF;
c=a+b;
是否有可能覆盖c旁边的内存位置?我希望在类型转换和赋值操作期间出现一些溢出标志或内存冲突标志。 场景4:假设32位处理器具有32位寄存器、32位寻址和sizeofint=32位:

unsigned int a, b;
struct {
    unsigned int c:16;
    unsigned int d:16;
} e;
a=0xFFFF;
b=0xFFFF;
e.c=a+b;
是否有可能覆盖c旁边的内存位置,即d?在这种情况下,由于c和d预期位于同一个32位地址中,并且从技术上讲都是32位整数,因此可以想象,在加法或赋值过程中不会出现溢出标志,d可能会受到影响。 我没有尝试在实际硬件上测试这一点,因为我的问题更多的是关于理论以及设计和实现中可能出现的变化。如有任何见解,将不胜感激

导致溢出的二进制整数操作是否可能覆盖相邻内存? 目前是否有任何硬件实现存在类似的内存覆盖问题,或者过去是否有系统存在此问题? 典型的处理器使用什么设备来防止相邻内存被算术和赋值操作覆盖?
1、2、3、4中的任何一个都不会导致内存损坏,也不会写入正在执行算术运算的整数位置的存储。C指定无符号整数溢出时应发生的情况。这是假设编译器生成它应该生成的代码。没有什么能阻止你使用一个错误的编译器,它会生成将4个字节复制到2个字节变量中的代码

以下是C99 6.2.5的内容:

涉及无符号操作数的计算永远不会溢出, 因为无法由结果无符号整数类型表示的结果是 约化模:比可计算的最大值大一的数 由结果类型表示

因此,当您试图溢出一个无符号整数时,将会发生什么,这是一个很好的定义

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

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

在赋值和算术运算方面,没有对相邻内存的保护。处理器只执行给定给它的机器代码指令,如果这些指令覆盖了内存,则不支持它按照更高级别的语言来执行,处理器不在乎


在稍微不同的级别上,如果CPU不能执行操作E.g,则可能会出现问题。操作指定的内存位置不存在,或试图执行某些非法操作(如除零),或遇到处理器不理解的操作码,或试图执行未对齐的数据访问。

1,2,3,4都不会导致内存损坏,或者写入正在执行算术运算的整数位置的存储。C指定无符号整数溢出时应发生的情况。这是假设编译器生成它应该生成的代码。没有什么能阻止你使用一个错误的编译器,它会生成将4个字节复制到2个字节变量中的代码

以下是C99 6.2.5的内容:

涉及无符号操作数的计算永远不会溢出, 因为一个不能用t表示的结果 生成的无符号整数类型为 约化模:比可计算的最大值大一的数 由结果类型表示

因此,当您试图溢出一个无符号整数时,将会发生什么,这是一个很好的定义

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

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

在赋值和算术运算方面,没有对相邻内存的保护。处理器只执行给定给它的机器代码指令,如果这些指令覆盖了内存,则不支持它按照更高级别的语言来执行,处理器不在乎


在稍微不同的级别上,如果CPU不能执行操作E.g,则可能会出现问题。该操作指定的内存位置不存在,或试图执行某些非法操作(如除零),或遇到处理器不理解的操作码,或试图执行未对齐的数据访问。

加法操作在处理器afaik内部处理,因此无论您做什么,添加操作将在ALU中的CPU内更精确地完成 溢出寄存器将在发生溢出时设置,结果仍将在寄存器中,然后复制回内存位置,而不会损坏相邻内存。 这就是代码在asm中的翻译方式:

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中已知且固定大小的内容

加法操作在处理器afaik内处理,因此无论您做什么,加法操作都将在ALU的CPU内更精确地执行 溢出寄存器将在发生溢出时设置,结果仍将在寄存器中,然后复制回内存位置,而不会损坏相邻内存。 这就是代码在asm中的翻译方式:

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中已知和固定大小的内容,无论是否发生溢出

在c中,无符号类型的溢出行为是明确定义的。溢出导致标准预测之外的任何结果的任何实现都是不符合的

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

对于溢出发生时发生的情况,其他语言可能有不同的语义


注意:我见过一些处理器在溢出时陷阱,一些处理器在外部中断同时发生意外陷阱可能导致数据损坏,而一些处理器在意外无符号溢出时可能导致后续计算关闭一次。我不知道有符号溢出在哪里会锁定一个会干扰后续计算的标志,但是一些DSP有有趣的溢出行为,因此如果有溢出行为,我不会感到惊讶。

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

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

对于溢出发生时发生的情况,其他语言可能有不同的语义

注意:我见过一些处理器在溢出时陷阱,一些处理器在外部中断同时发生意外陷阱可能导致数据损坏,而一些处理器在意外无符号溢出时可能导致后续计算关闭一次。我不知道在哪里
签名溢出会锁定一个会干扰后续计算的标志,但一些DSP具有有趣的溢出行为,因此,如果存在,我也不会感到惊讶。

这不是更多地说明了特定语言的实现如何像C一样处理将整数赋值给较小整数类型的变量吗?我会说答案是否定的,对于任何合理的体系结构和编程语言,请参阅,以获取关于旧体系结构上可能发生的事情的有趣的说明,如果可能的话…:-@delnan:是的,这个问题可能严重依赖于语言,但由于所有语言在运行之前都必须转换为机器代码,因此它们在硬件级别上有一个共同点。这些示例使用了类似C的语法,因为我相信大多数SO读者都可以最容易地访问它。类似于汇编的语法可能更适合这些问题,但可能无助于理解我的观点。。。再说一次,在机器代码中构造它可能会给我带来“啊哈!”但所有语言,即使是C语言,都定义了自己的一套规则。有些可能指定非常严格的截断规则,有些可能未定义。这不是关于特定语言的实现如何处理整数分配给较小整数类型的变量的更多信息吗?我认为答案是否定的,对于任何合理的体系结构和编程语言,请参阅,以获取关于旧体系结构上可能发生的事情的有趣的说明,如果可能的话…:-@delnan:是的,这个问题可能严重依赖于语言,但由于所有语言在运行之前都必须转换为机器代码,因此它们在硬件级别上有一个共同点。这些示例使用了类似C的语法,因为我相信大多数SO读者都可以最容易地访问它。类似于汇编的语法可能更适合这些问题,但可能无助于理解我的观点。。。再说一次,在机器代码中构造它可能会给我带来“啊哈!”但所有语言,即使是C语言,都定义了自己的一套规则。有些可能指定非常严格的截断规则,另一些可能未定义。这是所有合理的现代处理器的情况,即我所知道的不到40年的处理器。虽然C和C++定义了无符号整数溢出,所以不可能有所有可能的处理器,这样就不可能有额外的重写。我从来没有见过任何人,虽然我从来没有见过超过30岁的人,那是在我出生之前很久-这是所有合理的现代处理器的情况,也就是说,据我所知不到40岁。虽然C和C++定义了无符号整数溢出,所以不可能有所有可能的处理器,这样就不可能有额外的重写。我从来没有见过任何人,虽然我从来没有见过超过30岁的人,那是在我出生之前很久-