当我编译简短的 C 代码时,我得到“检测到堆栈崩溃”,而 JavaScript 中的相同代码运行正常,这是为什么?

问题描述 投票:0回答:2

这是一个更大项目的一部分,但我将错误的罪魁祸首隔离为这个特定的片段并对其进行了调整,以便它可以自行运行(包括预定义数字的值)。

#include <stdio.h>

int main() {
    unsigned number = 4;
    int array[] = {};
    for (int j = 0; j < number; j++) {
        for (int i = number; i > j; i--) {
            array[j] = i;
        }
        printf("%d ", array[j]);
    }
    return 0;
}

刚开始学C,想看看是不是代码本身的问题,不是C特有的,所以改成JavaScript:

var number = 4;
var array = [];
for (var j = 0; j < number; j++){
    for (var i = number; i > j; i--){
            array[j] = i;
        }
        console.log(array[j]);
    }

它运行并给了我预期的结果。使我收到错误的 C 代码有什么问题? 我尝试运行 C 代码,希望打印出数字 1、2、3 和 4。 相反,我收到了“检测到堆栈粉碎”错误消息。

arrays c memory-management dynamic-memory-allocation
2个回答
3
投票

你的代码的问题是你在 c 中声明了一个数组,但没有指定数组的大小。 c 是一种古老的语言,c 中的数组字面意思是给你的那个大小的内存框。您不能像在 Python 等语言中那样做任何花哨的事情,例如增加大小和向数组添加新元素。更正此代码并使其“可运行”的一种方法是将数组的大小设置为 4:

unsigned number = 4;
int array[4];  // <----- here
for (int j = 0; j < number; j++) { 
    for (int i = number; i > j; i--) {
        array[j] = i;
    }
    printf("%d ", array[j]);
}
return 0;

虽然这是一个正确的代码,因为您正在遍历与变量

number
相对应的列表,但您可能认为修复它的一种方法是执行我在下面所做的事情:

unsigned number = 4;
int array[number];  // <----- here
for (int j = 0; j < number; j++) { 
    for (int i = number; i > j; i--) {
        array[j] = i;
    }
    printf("%d ", array[j]);
}
return 0;

虽然这对某些数字有效,但对大值会失败。要解释这一点,您需要知道分配在“堆栈”中的任何内容(您通常声明的任何变量或值)的大小都是在编译时确定的,换句话说,在程序实际运行之前。 所以如果你使用变量

number
作为数组的大小,编译器应该如何知道数组的大小是多少? 变量的值在编译时(运行时)确定。那么c编译器是做什么的呢?它会给它一个随机的大尺寸,如 80 或 800。

这就是为什么我们使用称为堆分配的东西。使用库

<stdlib.h>
和函数
malloc( size )
您可以从堆中分配内存。堆中的内存分配是在运行时完成的,从而解决了手头的问题。你需要给
malloc
我们想要的内存大小。所以这就是
size of int * size of the array
。要记住的一件事是使用
malloc
函数释放您使用
free
分配的任何数组。不这样做会导致内存泄漏,这本身就是另外一回事了。 代码的最终和正确版本应该是:

unsigned number = 4;
int *array = malloc(sizeof(int) * number); // <--- allocate memory from heap at run-time
for (int j = 0; j < number; j++) {
    for (int i = number; i > j; i--) {
        array[j] = i; 
    }
    printf("%d ", array[j]);
}
free(array); // free the allocated memory
return 0;

0
投票

退休忍者做对了。我假设因为编译器在数组中已经有值时会自动定义数组的大小,所以它会做同样的事情,但现在我想到了,当然一旦代码已经运行它就不能这样做了。谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.