簡體   English   中英

C 代碼在 64 位 Ubuntu 14.04 中工作,但在 32 位 Ubuntu 14.04 中失敗

[英]C code works in 64-bit Ubuntu 14.04 but fails in 32-bit Ubuntu 14.04

#include <stdio.h>
#include <stdlib.h>

int count = 0;

int * new_array() {
    int i, *array = (int *) malloc(sizeof(int) * 9);

    for(i = 0; i <= 9; i++)
        array[i] = count++;

    for(i = 0; i <= 9; i++)
        printf("%d ", array[i]);
    printf("\n");

    return array;
}

int main(void) {
    int i;
    int *a;
    for(i = 0; i < 10; i++) {
        a = new_array();
    }
    return 0;
}

這在 64 位上運行良好,輸出符合預期。

但是,在 32 位中,輸出結果為:0 1 2 3 4 5 6 7 8 9

並出現錯誤信息:

prog: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.

我不明白為什么。 就我而言,它也應該在 64 位中失敗,因為我只分配了 9 個整數大小但訪問了數組的第 10 個元素。 如果是這樣,我為什么要關心長度? 我可以給出一個隨機數作為長度。

由於您在malloc()調用中僅為9元素分配內存,但稍后,使用返回的指針,您正在編寫

for(i = 0; i <= 9; i++)
    array[i] = count++;

這實際上是一個逐一的場景,本質上是越界訪問內存,創建未定義的行為

FWIW,UB的輸出是UB,與32位或64位架構無關。

也就是說,在直接使用返回的指針之前,始終通過針對 NULL 測試其返回值來檢查malloc()是否成功。

另外,請看看為什么不在C中轉換malloc()和 family 的返回值。

如果您在調用未定義行為時可以確定地期望某個行為,那么它就不會是未定義的。 您的問題在這里找到:

輸出符合預期

除了由於您沒有分配 10 個項目而導致數組越界訪問的核心問題之外,您的程序還存在以下問題:

錯誤

  • 您永遠不會釋放任何內存,並且每次調用該函數都會造成內存泄漏。 您還應該檢查 malloc 的結果。

代碼風格/不良做法

  • 避免在 C 中使用new_array()函數聲明。它的意思是“接受任何東西”作為參數。 這是 C 的一個過時特性,可能會從語言中刪除。 相反,將您的函數定義為int * new_array (void)

  • 不要使用全局變量。 count可以在函數內部聲明為局部靜態變量,或者更好的是,將其作為參數傳遞給函數。

  • 轉換 malloc 的結果是無害的,但也毫無意義

您可能會受益於現代 C11 編譯器。 看起來您仍在編寫舊的 C90 代碼。

就我而言,它也應該在 64 位中失敗,因為我只分配了 9 個整數大小但訪問了數組的第 10 個元素。

這會導致未定義的行為,這可能意味着立即出現段錯誤運行完成而沒有明顯問題破壞您的程序狀態,從而導致稍后發生故障等。

這是語言無法保護您免受自己傷害的眾多領域之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM