Каков максимально допустимый размер для объявления в стеке? - PullRequest
2 голосов
/ 23 марта 2012

Я использую Visual Studio 2010.

У меня есть массив трехмерной структуры, который, я думаю, дает мне неправильную ошибку.Массив определяется от

#define BUCKETS 2048
#define B_ENTRIES 4096

typedef struct fpinfo
{
    unsigned long long offset;
    unsigned long length;
     char fing_print[33];
}fpinfo;

как

struct fpinfo search_buf[TNK_CACHE_SIZE][BUCKETS][B_ENTRIES];

Проблема в том,

, когда я определяю TNK_CACHE_SIZE до 6, он не даетмне ошибка времени компиляции, но есть ошибка нарушения доступа во время выполнения, когда я пытаюсь записать в него.

с другой стороны, если я определяю TNK_CACHE_SIZE в 3, это дает мне следующееОшибка времени компиляции.

1> ССЫЛКА: фатальная ошибка LNK1248: размер изображения (86CB7000) превышает максимально допустимый размер (80000000)

1) Почему игнорируется первыйобъявление во время компиляции, но не для второго, когда оно составляло только половину первого.

2) Каков максимально допустимый размер объявления в стеке?

3) Включает ли этот допустимый размер все остальные выделения памяти в проекте или это одно выделение памяти за другим до тех пор, пока не останется больше не выделяемой области памяти и последний не былмогут быть выделены помечены?

Ответы [ 4 ]

2 голосов
/ 23 марта 2012

Не рекомендуется размещать такой большой объект в стеке, но вы можете переопределить размер стека по умолчанию для MSVC двумя способами:

  • Используйте параметр /F Свойства проекта перейдите в раздел C / C ++ , затем Командная строка и введите / F: байт в Дополнительные параметры *Поле 1015 *. В любом случае это не очень хорошая идея, потому что оно работает только для одного шага компиляции и компоновки.

  • В Свойствах проекта перейдите в Линкер раздел, затем Система и укажите необходимый размер в поле Резервный размер стека .

2 голосов
/ 23 марта 2012

Проверка компилятором и компоновщиком размера изображения, вероятно, несовершенна.Если вы сделаете его слишком большим, возможно, некоторые вычисления обернутся вокруг, что приведет к неверному результату, который, кажется, находится в допустимом диапазоне размеров изображения.Т.е. ваша цепочка инструментов поймает небольшую ошибку при слишком большом размере изображения, но не большую ошибку.

Обратите внимание, что если вы удвоите число 86CB,7000, вы получите такой, для представления которого требуется более 32 бита именно 1,0D96,E000.Если вычисление выполняется в 32 битах, это может быть уменьшено до D96,E000, в результате чего размер изображения будет выглядеть в диапазоне, хотя и совершенно неверно.

Попробуйте динамически выделить пространство с помощью malloc.

1 голос
/ 23 марта 2012

Простой факт заключается в том, что этот массив не должен быть объявлен в стеке.

Типичный размер стека в Windows составляет 2 МБ на поток. Обратите внимание, что это на поток , поэтому, даже если бы вы могли сделать стек слишком большим, ваша система, похоже, остановилась бы. Я даже не уверен, что подкачка дисков виртуальной памяти поддерживается для стековых данных, но ваш код будет работать очень медленно, если он это сделает.

Статическое или динамическое распределение было бы более уместным, но даже в этом случае это большая нагрузка для большинства систем, особенно 32-битных. Может быть более эффективно использовать отображенный в памяти файл. Это работает так же, как и при смене диска, но вы явно запрашиваете его, а не позволяете менеджеру памяти ОС принимать это решение недетерминированным образом.

0 голосов
/ 23 марта 2012

3 *2048* 4096 * sizeof (pinfo) составляет более гигабайта. Это только для вашего стола, так что да, ваше изображение будет огромным и явно больше, чем то, что VS разрешит по умолчанию.

Вам лучше распределить эту память динамически.

/**
 * Allocate memory in a single contiguous block.  Be sure to free it
 * when you don't need it anymore.
 */
fpinfo *search_buf_store = malloc(sizeof *search_buf_store * 
                                  TNK_CACHE_SIZE * 
                                  BUCKETS * 
                                  B_ENTRIES);

/**
 * Declare search_buf as a pointer to a 2-d array, and set it to point
 * to the block we just allocated.  You can then index search_buf
 * as you would a regular 3-D array.  Just be sure that if you pass search_buf
 * to any functions, you declare it in the parameter list just like it's 
 * declared here.
 */
fpinfo (*search_buf)[BUCKETS][B_ENTRIES] = 
  (fpinfo (*)[BUCKETS][B_ENTRIES]) search_buf_store;
...