简体   繁体   中英

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;
}

This works fine in 64-bit and the output is as expected.

However, in 32-bit, the output turns out to be: 0 1 2 3 4 5 6 7 8 9

And the error message appears:

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.

I don't understand why. As I'm concerned, it also should fail in 64-bit, since I only allocated 9 integer-size but accessed the 10th element of array. If this is the case, why I should care about the length? I can just give a random number as the length.

As you're allocating memory for only 9 elements in the malloc() call but later, with the returned pointer, you're writing

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

which is actually an off-by-one scenario and essentially accssing memory out of bounds, creating undefined behaviour .

FWIW, the output of UB is UB, it has nothing to do with 32 or 64 bit architecture.

That said, always check for the success of malloc() by testing its return value against NULL, before making use of the returned pointer directly.

Also, please see why not to cast the return value of malloc() and family in C .

If you could deterministically expect a certain behavior when you invoke undefined behavior, it wouldn't be undefined. Your problem is found here:

the output is as expected

In addition to that core problem with array-out-of bounds access because you didn't alloc 10 items, your program also have the following issues:

Bugs

  • You never free any memory and for each call to the function, you create a memory leak. You should also check the result from malloc.

Code style/bad practice

  • Avoid using new_array() function declarations in C. It means "accept anything" as parameter. This is an obsolete feature of C which may be removed from the language. Instead, define your function as int * new_array (void)

  • Don't use global variables. count could be declared as a local static variable inside the function, or better yet, pass it as a parameter to the function.

  • Casting the result of malloc is harmless but also pointless .

You would likely benefit from a modern C11 compiler. It looks like you are still writing old C90 code.

As I'm concerned, it also should fail in 64-bit, since I only allocated 9 integer-size but accessed the 10th element of array.

Which leads to undefined behavior , which could mean an immediate segfault or run to completion with no apparent issues or corrupting your program state such that a failure occurs later on, etc.

This one of many areas where the language won't protect you from yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM