2013-10-01 31 views
1

我面臨問題與C庫函數strtoull這是返回我錯誤的輸出。glibc函數strtoull()失敗

int main(int argc, char *argv[]) 
    { 
    unsigned long long int intValue; 

    if(atoi(argv[2]) == 1) 
    { 
     intValue = strtoull((const char *)argv[1], 0, 10); 
    } 
    else 
    { 
// ... 
    } 

    printf("intValue of %s is %llu \n", argv[1], intValue); 

    return 0; 
    } 

我構建它們並生成32位和64位可執行文件,如str32_new和str64_new。 但是從32位exe文件接收的輸出是errorneous爲返回錯誤號:

strtoull將應該已經回到我的號碼5368709120爲傳遞的字符串「5368709120」,但它返回我1073741824.

# ./str32_new "5368709120" 1 
intValue of 5368709120 is 1073741824 

我注意到當我從字符串中減少一個字符時,它會顯示正確的輸出。

# ./str32_new "536870912" 1 
intValue of 536870912 is 536870912 

glibc的附連到32位的exe是

# readelf -Wa /home/str32_new | grep strt 
    [39] .shstrtab   STRTAB   00000000 002545 000190 00  0 0 1 
    [41] .strtab   STRTAB   00000000 0032f8 0002a4 00  0 0 1 
    0804a014 00000607 R_386_JUMP_SLOT  00000000 strtoull 
    6: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.0 (2) 
    55: 00000000  0 FILE LOCAL DEFAULT ABS strtoull.c 
    75: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]@GLIBC_2.0 
    77: 08048534 915 FUNC GLOBAL DEFAULT 15 my_strtoull 

glibc的連接到64位的exe是

# readelf -Wa /home/str64_new | grep strt 
    [39] .shstrtab   STRTAB   0000000000000000 001893 000192 00  0 0 1 
    [41] .strtab   STRTAB   0000000000000000 002cd0 00029b 00  0 0 1 
    0000000000601028 0000000700000007 R_X86_64_JUMP_SLOT  0000000000000000 strtoull + 0 
    7: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (2) 
    57: 0000000000000000  0 FILE LOCAL DEFAULT ABS strtoull.c 
    73: 00000000004006cc 804 FUNC GLOBAL DEFAULT 15 my_strtoull 
    82: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]@GLIBC_2.2.5 

64位的exe示出了正確的輸出,但一些系統上它也表現異常。 爲什麼在32位exe中的strtoull表現如此以及如何解決這個問題?

+0

5368709120&(爲0xffffffff)= 1073741824 – Leeor

+0

你的代碼做'#包括',不是嗎? – alk

+0

不,我沒有。 包括它可以解決問題。 – RKum

回答

1

我認爲這是由於溢出。在32bit中的int不能容納大的數字(最大爲4294967296)。 Leeor說,5368709120 & (0xffffffff) = 1073741824

int類型的最低限度爲32位寬,在大多數(如果不是全部)系統上只有32位寬。

2

好吧,所以我們已經確定,這是非常明顯的發生,因爲溢出,因爲值匹配時發生的事情,如果鑄造成32位int。

但是這並不能解釋所有的東西 - 你確實使用了strtoull,而不是更短的strtoul,它確實可以在64位二進制文​​件上工作。如果有的話,我很驚訝地看到,你甚至能夠調用更長的版本在32位版本(你是怎麼通過的方式建造它,使用-m32?或者一個特殊的機器?)

This link,提高可能有一些連接現象使得strtoull被聲明爲int strtoll()(大概是系統無法支持原始的lib版本),所以我們得到的值通過int隱式轉換,然後再複製回你的unsigned long long。

無論哪種方式 - 這應該是由編譯器警告說,試圖將它設置爲C99,提高預警水平,也許這將使它喊

+0

同意。它可能甚至是一些愚蠢的東西,因爲不包括用於printf的頭文件,並且參數被降爲int。 – domen

+2

我沒有包含stdlib.h。 包括它可以解決問題。 – RKum