#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
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.