sbrk系統函數在Ubuntu 18.04.4 LTS 64位系統中的一些疑問

//查找100以內的素數

#include <stdio.h>
#include <unistd.h>

//素數檢測函數
int isPrimer(int a)
{

    int i;
    for(i = 2; i < a; i++)
    {
        if(a % i == 0)
        {
            return 1;
        }
    }
    return 0;
}

int main(void)
{
    int i = 2;
    int b;
    int *r;
    int *p;
    p = sbrk(0);
    r = p;
    for (; i < 100; i++)
    {
        b = isPrimer(i);
        if (b == 0)
        {
            brk(r + 1);
            *r = i;
            r = sbrk(0);
            //printf("i = %d, sbrk(0) = %p\n", i, sbrk(0));
        }
    }


    r = p;
    printf("r = %p, sbrk(0) = %p\n", r, sbrk(0));
    
    while(r != sbrk(0))
    {
        printf("sbrk(0) = %p, r = %p : %d\n", sbrk(0), r, *r);
        r++;
        sleep(1);
    }


    return 0;
}

以上函數是一個查找100以內素數的一個簡易函數。

但在Ubuntu 18.04.4 LTS 64位系統中,卻在任意一次執行中出現瞭如下結果:

r = 0x556ca4041000, sbrk(0) = 0x556ca4041064
sbrk(0) = 0x556ca4063000, r = 0x556ca4041000 : 2
sbrk(0) = 0x556ca4063000, r = 0x556ca4041004 : 3
sbrk(0) = 0x556ca4063000, r = 0x556ca4041008 : 5
sbrk(0) = 0x556ca4063000, r = 0x556ca404100c : 7
sbrk(0) = 0x556ca4063000, r = 0x556ca4041010 : 11
sbrk(0) = 0x556ca4063000, r = 0x556ca4041014 : 13
sbrk(0) = 0x556ca4063000, r = 0x556ca4041018 : 17
sbrk(0) = 0x556ca4063000, r = 0x556ca404101c : 19
sbrk(0) = 0x556ca4063000, r = 0x556ca4041020 : 23
sbrk(0) = 0x556ca4063000, r = 0x556ca4041024 : 29
sbrk(0) = 0x556ca4063000, r = 0x556ca4041028 : 31
sbrk(0) = 0x556ca4063000, r = 0x556ca404102c : 37
sbrk(0) = 0x556ca4063000, r = 0x556ca4041030 : 41
sbrk(0) = 0x556ca4063000, r = 0x556ca4041034 : 43
sbrk(0) = 0x556ca4063000, r = 0x556ca4041038 : 47
sbrk(0) = 0x556ca4063000, r = 0x556ca404103c : 53
sbrk(0) = 0x556ca4063000, r = 0x556ca4041040 : 59
sbrk(0) = 0x556ca4063000, r = 0x556ca4041044 : 61
sbrk(0) = 0x556ca4063000, r = 0x556ca4041048 : 67
sbrk(0) = 0x556ca4063000, r = 0x556ca404104c : 71
sbrk(0) = 0x556ca4063000, r = 0x556ca4041050 : 73
sbrk(0) = 0x556ca4063000, r = 0x556ca4041054 : 79
sbrk(0) = 0x556ca4063000, r = 0x556ca4041058 : 83
sbrk(0) = 0x556ca4063000, r = 0x556ca404105c : 89
sbrk(0) = 0x556ca4063000, r = 0x556ca4041060 : 97
sbrk(0) = 0x556ca4063000, r = 0x556ca4041064 : 0
sbrk(0) = 0x556ca4063000, r = 0x556ca4041068 : 0
sbrk(0) = 0x556ca4063000, r = 0x556ca404106c : 0
sbrk(0) = 0x556ca4063000, r = 0x556ca4041070 : 0

......

也即是在最後打印兩次sbrk(0)的返回值結果不一樣。

while循環之前sbrk(0)是正確的0x556ca4041064,

但在執行while循環時,sbrk(0)變成了0x556ca4063000,導致最後想打印100以內的素數時出現了錯誤。多打印了很多沒用的0值。

把sleep(1);去掉將會看見明顯的效果。

但是當我把printf("i = %d, sbrk(0) = %p\n", i, sbrk(0));這一句打開時,程序又得到了正常的運行。

i = 2, sbrk(0) = 0x55bbaa931004
i = 3, sbrk(0) = 0x55bbaa931008
i = 5, sbrk(0) = 0x55bbaa93100c
i = 7, sbrk(0) = 0x55bbaa931010
i = 11, sbrk(0) = 0x55bbaa931014
i = 13, sbrk(0) = 0x55bbaa931018
i = 17, sbrk(0) = 0x55bbaa93101c
i = 19, sbrk(0) = 0x55bbaa931020
i = 23, sbrk(0) = 0x55bbaa931024
i = 29, sbrk(0) = 0x55bbaa931028
i = 31, sbrk(0) = 0x55bbaa93102c
i = 37, sbrk(0) = 0x55bbaa931030
i = 41, sbrk(0) = 0x55bbaa931034
i = 43, sbrk(0) = 0x55bbaa931038
i = 47, sbrk(0) = 0x55bbaa93103c
i = 53, sbrk(0) = 0x55bbaa931040
i = 59, sbrk(0) = 0x55bbaa931044
i = 61, sbrk(0) = 0x55bbaa931048
i = 67, sbrk(0) = 0x55bbaa93104c
i = 71, sbrk(0) = 0x55bbaa931050
i = 73, sbrk(0) = 0x55bbaa931054
i = 79, sbrk(0) = 0x55bbaa931058
i = 83, sbrk(0) = 0x55bbaa93105c
i = 89, sbrk(0) = 0x55bbaa931060
i = 97, sbrk(0) = 0x55bbaa931064
r = 0x55bbaa931000, sbrk(0) = 0x55bbaa931064
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931000 : 2
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931004 : 3
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931008 : 5
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa93100c : 7
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931010 : 11
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931014 : 13
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931018 : 17
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa93101c : 19
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931020 : 23
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931024 : 29
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931028 : 31
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa93102c : 37
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931030 : 41
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931034 : 43
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931038 : 47
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa93103c : 53
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931040 : 59
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931044 : 61
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931048 : 67
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa93104c : 71
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931050 : 73
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931054 : 79
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931058 : 83
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa93105c : 89
sbrk(0) = 0x55bbaa931064, r = 0x55bbaa931060 : 97


而在Ubuntu 14.04.6 LTS 32位或者版本中,得到正確的執行。如下所示:

r = 0x9d52000, sbrk(0) = 0x9d52064
sbrk(0) = 0x9d52064, r = 0x9d52000 : 2
sbrk(0) = 0x9d52064, r = 0x9d52004 : 3
sbrk(0) = 0x9d52064, r = 0x9d52008 : 5
sbrk(0) = 0x9d52064, r = 0x9d5200c : 7
sbrk(0) = 0x9d52064, r = 0x9d52010 : 11
sbrk(0) = 0x9d52064, r = 0x9d52014 : 13
sbrk(0) = 0x9d52064, r = 0x9d52018 : 17
sbrk(0) = 0x9d52064, r = 0x9d5201c : 19
sbrk(0) = 0x9d52064, r = 0x9d52020 : 23
sbrk(0) = 0x9d52064, r = 0x9d52024 : 29
sbrk(0) = 0x9d52064, r = 0x9d52028 : 31
sbrk(0) = 0x9d52064, r = 0x9d5202c : 37
sbrk(0) = 0x9d52064, r = 0x9d52030 : 41
sbrk(0) = 0x9d52064, r = 0x9d52034 : 43
sbrk(0) = 0x9d52064, r = 0x9d52038 : 47
sbrk(0) = 0x9d52064, r = 0x9d5203c : 53
sbrk(0) = 0x9d52064, r = 0x9d52040 : 59
sbrk(0) = 0x9d52064, r = 0x9d52044 : 61
sbrk(0) = 0x9d52064, r = 0x9d52048 : 67
sbrk(0) = 0x9d52064, r = 0x9d5204c : 71
sbrk(0) = 0x9d52064, r = 0x9d52050 : 73
sbrk(0) = 0x9d52064, r = 0x9d52054 : 79
sbrk(0) = 0x9d52064, r = 0x9d52058 : 83
sbrk(0) = 0x9d52064, r = 0x9d5205c : 89
sbrk(0) = 0x9d52064, r = 0x9d52060 : 97

ubuntu18和ubuntu14 gcc 編譯器版本不同。

爲什麼會導致這個問題呢?sbrk(0)返回值在沒有重新分配空間的情況下爲什麼會變化呢?

是gcc編譯器版本的問題嗎?還是不同的內核版本導致了sbrk系統函數的運行機制不同?或者是64位和32位系統導致的差異?

可能需要更多實驗,或者查找一些書籍來弄明白這個問題。

也希望知道答案的朋友能留言告訴我。謝謝!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章