Форум программистов, компьютерный форум CyberForum.ru

Выделите-ка под массив память размером 32 ГБ - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.79
Ivan Fantom
 Аватар для Ivan Fantom
5 / 5 / 1
Регистрация: 12.10.2011
Сообщений: 75
11.07.2013, 22:45     Выделите-ка под массив память размером 32 ГБ #1
Получил ряд вопросов от одной фирмы. Надо ответить чтобы удостоить себя собесодованием) Вот один из них.

Словесно представьте вашу последовательность действий при написании программного кода заданий описанных ниже с учетом всех возможных на Ваш взгляд багов:

а) Приведите любой пример выделения памяти под массив, где размер выделяемой памяти должен составлять = 235 байт и заполните его случайными значениями.

б) Переэлокейтите массив, чтобы его размерность увеличилась с 235 до 235 + 100.

Про а)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    unsigned long long size = 1024*1024*1024;
    size *= 32;
 
    char* ms = new char[size];
    
    for(int i=0;i<size;i++)
        ms[i] = i + '0';
 
    cout << ms[size-1] << endl;
 
    delete[] ms;
    return 0;
}
Само выделение памяти прошло без проблем, а вот когда началась инициализация, то на 1305 ячейке массива вижла сообщает об ошибке.
Изначально я понимал, что выделить такой большой кусок памяти тривиальными средствами не получится. Но я просто не знаю какими средствами можно решить поставленную задачу.
Миниатюры
Выделите-ка под массив память размером 32 ГБ  
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
12.07.2013, 11:24     Выделите-ка под массив память размером 32 ГБ #21
Где-то на форуме уже писал про это - на 64 битной ОС добиться std::bad_alloc еще постараться надо. Дело в том, что оператор new() работает с виртуальными адресами, и ничего не мешает выделить, например, 1 ТБ (это под Linux, в винде есть ограничение памяти на процесс, вроде 17 гигов, но точно не помню). Если выделить 10 ТБ, то никакого std::bad_alloc не будет, все пройдет хорошо. Проблемы начнутся при записи/чтении в/из этой памяти. Потому обертывать new в try{}catch(){} на 64 битной ОС по сути бесполезное занятие.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
12.07.2013, 14:45     Выделите-ка под массив память размером 32 ГБ #22
Цитата Сообщение от Kastaneda Посмотреть сообщение
Где-то на форуме уже писал про это - на 64 битной ОС добиться std::bad_alloc еще постараться надо. Дело в том, что оператор new() работает с виртуальными адресами, и ничего не мешает выделить, например, 1 ТБ (это под Linux, в винде есть ограничение памяти на процесс, вроде 17 гигов, но точно не помню). Если выделить 10 ТБ, то никакого std::bad_alloc не будет, все пройдет хорошо. Проблемы начнутся при записи/чтении в/из этой памяти. Потому обертывать new в try{}catch(){} на 64 битной ОС по сути бесполезное занятие.
Вот код и результат на 64-битной XP:
C++
1
2
3
4
5
6
7
8
9
int main()
{
    unsigned long long size = 1024*1024*1024;
    size *= 32;
 
    char* ms = new char[size];
    
    return 0;
}
Миниатюры
Выделите-ка под массив память размером 32 ГБ  
Programmer c
 Аватар для Programmer c
5 / 0 / 2
Регистрация: 06.07.2013
Сообщений: 59
12.07.2013, 15:05     Выделите-ка под массив память размером 32 ГБ #23
Многовато))) 32 гб)
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
12.07.2013, 15:09     Выделите-ка под массив память размером 32 ГБ #24
alsav22, я ж написал, что в винде ограничение на каждый процесс есть. Вот на 64 битном Linux'е запустил такой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
int main() 
{
    for (int i = 0; i < 1024 * 100; i++) { // всего "выделится" 100 ТЕРАбайт
        try {
            char *p = new char[1024 * 1024 * 1024];
        } catch (std::exception &e) {
            std::cout << e.what() << std::endl;
        }
    }
}
код отработал молча, т.е. память как бы выделилась.
alsav22
12.07.2013, 17:42
  #25

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
alsav22, я ж написал, что в винде ограничение на каждый процесс есть.
Прошу прощения, пропустил, что это про Linux пишется.

Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
12.07.2013, 17:53     Выделите-ка под массив память размером 32 ГБ #26
Цитата Сообщение от alsav22 Посмотреть сообщение
пропустил, что это про Linux пишется.
Не то, чтобы совсем под Linux, т.к. Windows это тоже касается. Даже несмотря на виндовые ограничения в x86_64 все равно можно "выделить" больше памяти, чем есть реально (ну только если физически все же меньше памяти, чем ограничение в N гигов).
У меня нет 64 битной винды, проверить доступный размер не могу, но, если кому не сложно, можно выполнить следующий код и выложить результат.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
int main() 
{
    for (int i = 0; i < 1024 * 100; i++) { 
        try {
            char *p = new char[1024 * 1024 * 1024];
            std::cout << i << "GB" << std::endl;
        } catch (std::exception &e) {
            std::cout << e.what() << std::endl;
            return 0;
        }
    }
}
если исключение выкинется сразу, то можно поступить так
C++
1
char *p = new char[1024 * 1024 * 1024 / 2];
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
12.07.2013, 18:03     Выделите-ка под массив память размером 32 ГБ #27
Это при 4Гб памяти.
Миниатюры
Выделите-ка под массив память размером 32 ГБ  
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
12.07.2013, 18:09     Выделите-ка под массив память размером 32 ГБ #28
Хм, странно, я своими глазами видел, как винда выдавала сообщение про ограничение в 17 (точно не помню) GB. Может в винде такие вещи где-то настраиваются.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
12.07.2013, 18:28     Выделите-ка под массив память размером 32 ГБ #29
Но не болше же чем физической памяти?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
12.07.2013, 19:22     Выделите-ка под массив память размером 32 ГБ #30
Kastaneda, Данный код подвесил мою систему наглухо... bad_alloc не дождался... Вообщем, жесть)
В release после 3 ГБ вышел bad_alloc, 4 ГБ в системе.
http://stackoverflow.com/questions/4...e-in-a-program
On 32-bit Windows your application would stop at 4GB. On 64-bit Windows your application will stop at 16TB (assuming you have a page file that can grow automatically, and that much hard disk space).
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
12.07.2013, 19:35     Выделите-ка под массив память размером 32 ГБ #31
Цитата Сообщение от ForEveR Посмотреть сообщение
Данный код подвесил мою систему наглухо..
Интересно получается. Под линуксом этот код выполняется довольно быстро и на систему ни как не влияет (хотя я за памятью не следил во время выполнения). А под виндой похоже память реально пытается выделиться (раз система виснет) и, когда ОЗУ заканчивается, то место ищется на харде (хотя я не совсем понимаю как работает винда). В линуксе же размер swap'a тоже ограничен, а в винде походу нет.

Добавлено через 3 минуты
Цитата Сообщение от Kastaneda Посмотреть сообщение
а в винде походу нет.
а не, гоню, ограничен. И его руками поменять можно.

Добавлено через 2 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
Данный код подвесил мою систему наглухо... bad_alloc не дождался...
а, кстати, сколько гигов оно успело выделить прежде чем повиснуть?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
12.07.2013, 19:38     Выделите-ка под массив память размером 32 ГБ #32
Kastaneda, 1 или 2. Но это был дебаг. В релизе все крайне быстро
Kastaneda
12.07.2013, 19:42
  #33

Не по теме:

За что люблю линукс, так это за то, что когда что-то не понятно, можно взять и посмотреть в исходниках как оно реально работает. А когда в винде что-то непонятно, нужно искать ответ на msdn, если там не нашел, то гуглить, если не нагуглил, то спросить на форуме, если на форуме не помогут, то ответа на свой вопрос ты так и не узнаешь (если конечно нет желания погрузиться на несколько месяцев в дизассемблер).

Bend3r
 Аватар для Bend3r
142 / 129 / 17
Регистрация: 29.07.2012
Сообщений: 687
12.07.2013, 19:57     Выделите-ка под массив память размером 32 ГБ #34
Я пока еще не опытен в C++, но по-моему можно же сделать так.
К сожалению, я не знаю сколько памяти занимает тип int (2 по-моему).
Допустим вам надо выделить 256 кб, ну и примерно так int *a = new int[128];

//Если я в чем-то не прав, разьясните пожалуйста в чем..
Thinker
Эксперт C++
 Аватар для Thinker
4215 / 2189 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
12.07.2013, 20:07     Выделите-ка под массив память размером 32 ГБ #35
Цитата Сообщение от Bend3r Посмотреть сообщение
К сожалению, я не знаю сколько памяти занимает тип int (2 по-моему).
все зависит от версии компилятора и марки компьютера. и 2 байта, и 4 бывают.
Kuzia domovenok
 Аватар для Kuzia domovenok
1883 / 1738 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
12.07.2013, 21:36     Выделите-ка под массив память размером 32 ГБ #36
Цитата Сообщение от Kastaneda Посмотреть сообщение
За что люблю линукс, так это за то, что когда что-то не понятно, можно взять и посмотреть в исходниках как оно реально работает. А когда в винде что-то непонятно, нужно искать ответ на msdn, если там не нашел, то гуглить, если не нагуглил, то спросить на форуме, если на форуме не помогут, то ответа на свой вопрос ты так и не узнаешь (если конечно нет желания погрузиться на несколько месяцев в дизассемблер).
по-моему, это наоборот одна из многочисленных причин ненавидеть Linux.
Цитата Сообщение от Bend3r Посмотреть сообщение
Я пока еще не опытен в C++, но по-моему можно же сделать так.
К сожалению, я не знаю сколько памяти занимает тип int (2 по-моему).
Допустим вам надо выделить 256 кб, ну и примерно так int *a = new int[128];
Если смотреть на достаток/нехватку памяти, то результат этих операций будет одинаков.
C++
1
2
int *a = new int[N];
char *b = new char[N*sizeof(int)];
Kastaneda
12.07.2013, 21:39
  #37

Не по теме:

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
по-моему, это наоборот одна из многочисленных причин ненавидеть Linux.
Kuzia domovenok, я промолчу потому что очень очень неохото разводить очередной холивар

alsav22
13.07.2013, 02:41
  #38

Не по теме:

Цитата Сообщение от Bend3r Посмотреть сообщение
//Если я в чем-то не прав, разьясните пожалуйста в чем..
В том, что не читаете предыдущих постов.

Ivan Fantom
 Аватар для Ivan Fantom
5 / 5 / 1
Регистрация: 12.10.2011
Сообщений: 75
13.07.2013, 03:18  [ТС]     Выделите-ка под массив память размером 32 ГБ #39
Ребята, вы ушли в сторону от задачи.
Итак malloc/new 32 ГБ никак не выделят. Вдобавок size_t просто урежет значение переменной размера.

Я пробовал использовать функции VirtualAlloc и VirtualFree, которые являются более гибкими средствами выделения памяти.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <malloc.h>
#include "windows.h"
#include <iostream>
using namespace std;
 
void main()
{
    size_t MEMSIZE = 6442450944ULL; //6GB
    char* p = (char*)VirtualAlloc(NULL,MEMSIZE,MEM_COMMIT,PAGE_READWRITE);
 
    if (p!=NULL)
        cout << "OK Alloc " << endl;
    else
    {
        cout << "Error Alloc " << endl;
        
        if (VirtualFree(p,0,MEM_RELEASE))
            cout << "Ok Free";
        else cout << "Not Free" << endl;
        return;
    }
    
    for(size_t i = 0;i<MEMSIZE;i++)
        *(p+i) = (int)i + '0';
 
    cout << p[MEMSIZE-1] << endl;
 
    if (VirtualFree(p,0,MEM_RELEASE))
        cout << "Ok Free";
    else cout << "Not Free" << endl;
}
И результат был таков.

Конфигурация проекта Win32. Память выделилась (с предупреждением об усечении значения переменной размера) размером в 4096, что вполне ожидаемо, ведь VirtualAlloc память выделяет блоками по 4096 байт, и соответственно указанный размер будет округляться до этого числа.

Конфигурация проекта x64. VirtualAlloc возвращает нулевой указатель, что говорит о неудачном выделении. Зато успешно выделялась и заполнялась случайными значениями память объемом 2 ГБ, 3 ГБ. При 5 ГБ вся моя оперативная память была занята и система зависла.

Есть еще такой механизм свопинга, заключающийся в том, что каждый процесс полностью переносится в память, работает некоторое время и потом целиком возвращается на диск. Другая стратегия – виртуальная память – позволяет программам работать даже тогда, когда они частично находятся в оперативной памяти.
Система использует механизм виртуализации адресов при необходимости, но почему-то на мое приложение механизм не распространяется, когда объем выделяемой памяти превышает объем свободной оперативной памяти.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.07.2013, 10:06     Выделите-ка под массив память размером 32 ГБ
Еще ссылки по теме:

выделить и удалить память под 4 мерный массив C++
Как выделить память под динамический двумерный массив C++
C++ Выделить память под массив размера 2^64 байтов

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Убежденный
Системный программист
 Аватар для Убежденный
14217 / 6232 / 988
Регистрация: 02.05.2013
Сообщений: 10,390
Завершенные тесты: 1
13.07.2013, 10:06     Выделите-ка под массив память размером 32 ГБ #40
Цитата Сообщение от Ivan Fantom Посмотреть сообщение
Ребята, вы ушли в сторону от задачи.
Как мне кажется, смысл данной задачи не в том, чтобы найти способ выделить 32 ГБ под
массив, а в том, чтобы предложить хорошую абстракцию для работы с таким массивом.
Например, можно написать что-то вроде класса large_array, который будет хранить свое
содержимое на диске, в 32-гигабайтном файле, и предоставлять клиентам доступ к нужным
элементам, загружая их в память по мере необходимости. На Windows наиболее естественным
для этого будет использовать отображаемые в память файлы. Сверху можно навесить кэш, в
котором хранить некоторое количество последних элементов, запрошенных клиентами, для
ускорения доступа (чтобы не дергать диск каждый раз). Но в любом случае это получится
"дырявая" абстракция: с таким массивом нельзя будет работать также, как с обычным -
доступ к памяти нужно будет делать косвенный, например, через дескрипторы, не будет
безопасным выполнять memset на диапазоне элементов такого массива, и т.п.

Цитата Сообщение от Ivan Fantom Посмотреть сообщение
Конфигурация проекта Win32. Память выделилась (с предупреждением об усечении значения переменной размера) размером в 4096, что вполне ожидаемо, ведь VirtualAlloc память выделяет блоками по 4096 байт, и соответственно указанный размер будет округляться до этого числа.
Задача о выделении 32-гигабайтного массива в 32-разрядном процессе нерешаема в принципе.
В каталоге страниц памяти 32-битного процесса просто нет столько места, чтобы хранить
описание массива в 32 гигабайта. Пользовательским процессам в 32-битном адресном
пространстве доступно чуть меньше 2 гигабайт, ключ /3GB принципиально картины не меняет.
О непрерывном блоке памяти такого размера в 32-битном процессе можно забыть.

Цитата Сообщение от Ivan Fantom Посмотреть сообщение
Конфигурация проекта x64. VirtualAlloc возвращает нулевой указатель, что говорит о неудачном выделении.
Не хватило файла подкачки, скорее всего (проверьте GetLastError == 1455).
Кстати, вместо увеличения файла подкачки можно выделить зарезервированный блок (MEM_RESERVE)
охраняемых страниц (PAGE_GUARD) и коммитить их только при попытках доступа, а старые страницы
при этом снова отправлять в резерв. То есть, получится такой аллокатор памяти с отслеживанием
нарушений доступа по исключению. Система использует этот механизм для динамического увеличения
размера стека.

Цитата Сообщение от Ivan Fantom Посмотреть сообщение
Система использует механизм виртуализации адресов при необходимости,
но почему-то на мое приложение механизм не распространяется, когда объем выделяемой памяти
превышает объем свободной оперативной памяти.
Распостраняется. Виртуальная память используется всегда, ее поддержка обеспечена аппаратно, в
том числе на уровне CPU. Но существует путаница между виртуальной памятью и файлом подкачки,
хотя это разные вещи.
Yandex
Объявления
13.07.2013, 10:06     Выделите-ка под массив память размером 32 ГБ
Ответ Создать тему
Опции темы

Текущее время: 22:50. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru