2015-05-04 11 views
0

Я хочу объявить длинный длинный массив без знака с 2mil. элементы. Когда я сначала определяю длину массива const, а затем определим массив, я получаю ошибку ошибки сегментации. Однако, когда я определяю длину так же, как unsigned long long, декларация работает.Ошибка сегментации в объявлении большого массива

int main(int argc, const char *argv[]) 
{ 
    const unsigned long long lim = 2000000; //If I omit const, it works. 
    unsigned long long nums2lim[lim]; 

    exit(EXIT_SUCCESS); 
} 

Кто-нибудь знает, почему возникает ошибка сегментации?

+1

Это не выглядит как C++ – Eregrith

+5

Ваш стек, скорее всего, не является достаточно большим для 2-х миллионов беззнаковых длинных долгот. – dwcanillas

+1

Локальные переменные, включая массивы, хранятся в стеке, а стек ограничен. В Windows стек по умолчанию - всего один мегабайт, в Linux - 8 МБ. Ваш массив почти * шестнадцать * МБ. –

ответ

0

Вы бы сделать это в C++, чтобы выделить данные в куче:

const unsigned long long lim = 2000000; 
unsigned long long *nums2lim = new unsigned long long[lim]; 
... 
delete [] nums2lim; 
+0

Вопрос помечен как C, поэтому нет выражений 'new' или' delete'. И @ TheParamagneticCroissant, не 'std :: vector'. –

+6

@JoachimPileborg извините, пропустил удаление тега C++. Я * ненавижу * это, когда люди отмечают свои вопросы как с C++, так и с C, а затем удаляют один из них. Это просто неправильно. –

2

Вы можете сделать практически то же самое с этим (он использует указатели)

#include <stdlib.h> 

int main(int argc, const char *argv[]) 
{ 
    unsigned long long lim = 2000000; 
    unsigned long long *nums2lim=malloc(lim*sizeof(unsigned long long)); 

    free(nums2lim); // don't forget this! 

    return EXIT_SUCCESS; 
} 
+0

И использование 'free', когда массив больше не нужен. – ChronoTrigger

+0

@ ChronoTrigger, да, я всегда забываю об этом при публикации ответов ... Спасибо, что заметили это, я отредактирую свой пост. – ForceBru

+0

Действительно, это хороший подход, но это не объясняет, почему он падает, когда я объявляю lim как cont unsigned long long. – bergercookie

1

Я не был в состоянии воспроизведите это поведение на моем блоке SLES 10 (gcc 4.1.2, да, он старый). Я получаю segfault независимо от того, как объявляется lim.

Я собираюсь идти путь, путь, путь, путь на очень тощего конечности и указывают на то, что ваше определение main неверно; argv не должен быть объявлен const (стандартное требование о том, что строки, на которые указывает массив argv, должны быть модифицируемыми). Этот бит неопределенного поведения может быть достаточно, чтобы вызвать разницу, но я серьезно сомневаюсь в этом.

В любом случае, пытаясь выделить 2 миллиона что-нибудь в массиве auto (VLA или нет) почти всегда плохой juju. Возможно, когда компьютерная память будет регулярно измеряться в терабайтах, это уже не будет проблемой, но на данный момент она будет больше, чем обычно выполняется для стека времени выполнения.

У вас есть несколько вариантов. Во-первых, вы можете объявить массив с длительностью хранения static, либо объявив его в области файла (вне любой функции), либо с помощью ключевого слова static. Обратите внимание, это означает, что вы будете не быть в состоянии использовать переменную lim указать размер (даже если вы объявляете его const, lim не константа, его значение не известно во время компиляции):

int main(int argc, char **argv) 
{ 
    static unsigned long long nums2lim[2000000]; 
    ... 
} 

в качестве альтернативы, вы можете выделить его из кучи во время выполнения:

int main(int argc, char **argv) 
{ 
    const unsigned long long lim=2000000; 
    int *nums2lim = malloc(sizeof *nums2lim * lim); 
    if (nums2lim) 
    { 
    ... 
    } 
    ... 
} 
Смежные вопросы