简体   繁体   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;
}

This works fine in 64-bit and the output is as expected.这在 64 位上运行良好,输出符合预期。

However, in 32-bit, the output turns out to be: 0 1 2 3 4 5 6 7 8 9但是,在 32 位中,输出结果为: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.就我而言,它也应该在 64 位中失败,因为我只分配了 9 个整数大小但访问了数组的第 10 个元素。 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由于您在malloc()调用中仅为9元素分配内存,但稍后,使用返回的指针,您正在编写

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. FWIW,UB的输出是UB,与32位或64位架构无关。

That said, always check for the success of malloc() by testing its return value against NULL, before making use of the returned pointer directly.也就是说,在直接使用返回的指针之前,始终通过针对 NULL 测试其返回值来检查malloc()是否成功。

Also, please see why not to cast the return value of malloc() and family in C .另外,请看看为什么不在C中转换malloc()和 family 的返回值。

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:除了由于您没有分配 10 个项目而导致数组越界访问的核心问题之外,您的程序还存在以下问题:

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.您还应该检查 malloc 的结果。

Code style/bad practice代码风格/不良做法

  • Avoid using new_array() function declarations in C. It means "accept anything" as parameter.避免在 C 中使用new_array()函数声明。它的意思是“接受任何东西”作为参数。 This is an obsolete feature of C which may be removed from the language.这是 C 的一个过时特性,可能会从语言中删除。 Instead, define your function as int * new_array (void)相反,将您的函数定义为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. count可以在函数内部声明为局部静态变量,或者更好的是,将其作为参数传递给函数。

  • Casting the result of malloc is harmless but also pointless .转换 malloc 的结果是无害的,但也毫无意义

You would likely benefit from a modern C11 compiler.您可能会受益于现代 C11 编译器。 It looks like you are still writing old C90 code.看起来您仍在编写旧的 C90 代码。

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.就我而言,它也应该在 64 位中失败,因为我只分配了 9 个整数大小但访问了数组的第 10 个元素。

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.这是语言无法保护您免受自己伤害的众多领域之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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