其他分享
首页 > 其他分享> > 一次int转换成unsigned long数值溢出问题

一次int转换成unsigned long数值溢出问题

作者:互联网

在项目中遇到一个奇怪的宕机问题,后来查询定位发现是erlang底层数据溢出问题,用c模拟情况类似,当一个int类型的x值大于等于1<<25的时候,再左移6位会造成nt溢出,然后再强转成64位无符号整数。

test_int.c

#include <stdio.h>

int main(){
    int a = 1;
    int x = (a<<25);
    int x1 = (x<<6)+10;
    unsigned long y = (unsigned long)(x1);
    y+=1;
    y+=1;
    y+=1;
    y+=1;
    printf("x=%d\n", x); 
    printf("x1=%d\n", x1);
    printf("y=%lu\n", y); 
    return 0;
}

输出结果

x=33554432
x1=-2147483638
y=18446744071562067982

gcc -S test_int.c

    subq    $32, %rsp
    movl    $1, -4(%rbp)      --- - -4(%rbp)表示a
    movl    -4(%rbp), %eax
    sall    $25, %eax
    movl    %eax, -8(%rbp) ----- -8(%rbp) 表示 x
    movl    -8(%rbp), %eax
    sall    $6, %eax
    addl    $10, %eax
    movl    %eax, -12(%rbp) ---- -12(%rbp) 表示x1
    movl    -12(%rbp), %eax ------ 这里开始符号扩展 
    cltq
    movq    %rax, -24(%rbp)
    addq    $1, -24(%rbp)
    addq    $1, -24(%rbp)
    addq    $1, -24(%rbp)
    addq    $1, -24(%rbp)
    movl    -8(%rbp), %eax
    movl    %eax, %esi

 

顺带再分析了一下32位有符号数转换成64位无符号数的时候在底层汇编会发生什么。

有符号数在底层都是用补码进行表示,转换成无符号数的时候需要根据最高位进行判断,最高位是1的话则用1来扩充,是0的话用0扩充。

cltq就是符号扩展指令,只对eax寄存器扩展到rax寄存器。
 


标签:24,movl,addq,int,unsigned,long,rbp,eax
来源: https://www.cnblogs.com/doudou1024/p/16156765.html