Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.226.96.61] |
|
Сообщ.
#1
,
|
|
|
Стандартный оператор new выделяет память не более 4 гигабайт. Существует ли возможность выделить больше памяти, может какая ни будь библиотека?
|
Сообщ.
#2
,
|
|
|
Цитата a_n_y_a @ Стандартный оператор new выделяет память не более 4 гигабайт. Откуда информация? Вот например почитай обсуждение: http://rsdn.org/forum/winapi/2786441.flat Там люди выделяют больше 4 гигабайт оператором new Но наверное лучше воспользоваться VirtualAlloc, как советуют в обсуждении. И хорошо подумать - а дествительно памяти надо больше 4 гигов? |
Сообщ.
#3
,
|
|
|
На другой компилятор перейти есть возможность? Например, вот это:
int main() { const size_t total = 5ll * 1024 * 1024 * 1024; char *ptr = new char[total]; ptr[0] = 'a'; ptr[total - 1] = 'z'; std::cout << ptr[0] << ptr[total - 1] << std::endl; } в clang работает нормально, в студии - нет. |
Сообщ.
#4
,
|
|
|
Цитата OpenGL @ в clang работает нормально, в студии - нет. #include <iostream> int main() { const size_t total = 5ll * 1024 * 1024 * 1024; char *ptr = nullptr; ptr = new char[total]; ptr[0] = 'a'; ptr[total - 1] = 'z'; std::cout << sizeof(size_t) << '\t' << reinterpret_cast<void*>(ptr) << '\n' << ptr[0] << ptr[total - 1] << std::endl; delete[] ptr; } VS 2017 8 000001180F591040 az |
Сообщ.
#5
,
|
|
|
Странно. У меня в operator new[] приходит аргумент типа size_t, но усечённый до uint32_t, т.е. в данном случае 1 гигабайт. И поэтому падает всё. VS 2019.
|
Сообщ.
#6
,
|
|
|
VS 2019
Консольный в 64x размер size_t - 8 16Гб оперативки (свободно 50%) Запускаем, выделение по диспетчеру 1Гб (1024,4), в программе ошибка доступа к последнему байту, указатель не нулевой. |
Сообщ.
#7
,
|
|
|
Сам по себе new память не выделяет, он вызывает malloc.
Значит, если есть ограничение, это ограничение malloc-a. Если всё-таки очень нужно использование new с очень большими объёмами, тогда можно попробовать new/delete перегрузить и использовать их вместе с VirtualAlloc/VirtualFree. |
Сообщ.
#8
,
|
|
|
Цитата ЫукпШ @ Значит, если есть ограничение, это ограничение malloc-a. Вряд ли. В данном случае именно в operator new[] уже приходит урезанное число. Позже проверю вызов с malloc |
Сообщ.
#9
,
|
|
|
Цитата ЫукпШ @ В Стандарте это нигде не гарантируется. Более того, он содержит утверждения, что allocation functions и C memory allocations являются разными средствами, работающими с разными аренами, хотя и не запрещает реализацию первых посредством вторых Сам по себе new память не выделяет, он вызывает malloc. |
Сообщ.
#10
,
|
|
|
А что в стандарте не предусмотрено, что если ты столько не можешь, то вернуть нуль???
Мы то получаем валидный указатель, но на меньший объем... |
Сообщ.
#11
,
|
|
|
Цитата Black_Dragon @ А что в стандарте не предусмотрено, что если ты столько не можешь, то вернуть нуль??? Мы то получаем валидный указатель, но на меньший объем... Что-то тут не таку вас.. Когда у меня не получилось, мне вернули NULL вместо адреса. я попробовал взять 2Г для x86 системы. --- А в целом всё получилось. Исходник всзял у Qraizer-а почти без изменений. Перегрузил new/delete чтобы следить за выделяемыми блоками. Собирал всё в VS2008 Express, WinXP Home Sp3 Исходник: Скрытый текст // --------------------------------------------------------------------------------- // Перегрузка операции new. inline void* __cdecl operator new(size_t size) { char* pt = typebuff; size_t sizeS = ARRAYSIZE(typebuff); size_t n = 0; void* p = malloc(size); n = SimpleRs::addr2asc(pt, sizeS, " p=0x", p); pt += n; sizeS -= n; #ifdef _M_IX86 n = SimpleRs::dword2dec (pt, sizeS, " size=", size); #endif #ifdef _M_AMD64 n = SimpleRs::qword2asc (pt, sizeS, " size=0x", (unsigned long long )size); #endif ::OutputDebugStringA(typebuff); return p; } // --------------------------------------------------------------------------------- // Перегрузка операции delete. inline void __cdecl operator delete(void *p) { free (p); } // --------------------------------------------------------------------------------- int __cdecl _tmain(int argc, TCHAR **argv) { ::OutputDebugString(_T("----- vvv -----")); #ifdef _M_IX86 size_t v1 = 2; #endif #ifdef _M_AMD64 size_t v1 = 5; #endif size_t v2 = 1024; size_t total = v1; total *= v2; total *= v2; total *= v2; char *ptr = NULL; ptr = new char[total]; ptr[0] = 'a'; ptr[total - 1] = 'z'; std::cout << sizeof(size_t) << '\t' << reinterpret_cast<void*>(ptr) << '\n' << ptr[0] << ptr[total - 1] << std::endl; delete[] ptr; ::OutputDebugString(_T("----- ^^^ -----")); } В итоге получилось так: Диагностика из Dbgview: За пределами "заборчика" - это работа старт-апа. |
Сообщ.
#12
,
|
|
|
Цитата Black_Dragon @ В Стандарте предусмотрено, что если allocation function не может вернуть блок запрошенного размера, то должна быть вызвана new-handler function, которая может быть установлена посредством std::set_new_handler(). Если таковой нет, должно быть брошено std::bad_alloc. Если таковая есть, то вызвать её и по возврату назад повторить попытку найти нужное количество памяти, и далее по циклу. В свою очередь к new-handler function предъявляются требования либо найти сколько-нибудь места и вернуть управление, либо бросить std::bad_alloc или производный от него, либо завершить программу без возврата. Учитывая, что требования к new-handler function обязан учитывать сам программист, который такую собрался писать, понятно, что любые несоответствия Стандарту тут, если таковые будут, следует предъявлять к нему, а не Стандарту.А что в стандарте не предусмотрено, что если ты столько не можешь, то вернуть нуль??? В черновике C++17 я не нашёл требования, как именно в последнем случае программа должна завершаться, однако во всех релизах Стандарта есть замечательная std::terminate(), как будто бы спецом для этого. На самом деле есть чёткий список, когда std::terminate() будет вызываться, и new-handler function там отсутствует. Вероятно, из-за того, что гарантировать соблюдение этих требований Стандарт в принципе не в состоянии, не от него это зависит. Цитата Black_Dragon @ Вот уж чего точно не может быть ни в коем случае. Если вдруг кто-то увидит перегруженный new который позволяет себе вести себя подобным образом, пусть смело кидает автору пожизненный страйк без выходного пособия. Мы то получаем валидный указатель, но на меньший объем... Добавлено P.S. Ты уверен, что правильно size_t приготовил, Black_Dragon? Например, 5*1024*1024*1024 – это неправильно. И даже 0x140000000 тоже неправильно. Добавлено P.P.S. В Стандарте предусмотрено сразу вернуть nullptr безо всяких new-handler function, но для этого вызывать нужно не просто new, а new (std::nothrow). |
Сообщ.
#13
,
|
|
|
Ха. Посмотрел сейчас ассемлерный выхлоп, поигрался с исходником... В общем, почему-то если size_t константа (компилил в дебаге с выключенной оптимизацией), то в operator new[] аргумент передаётся через ecx, так что неудивительно, что 8-байтовое целое урезается:
; 13 : char* ptr = new char[total]; mov ecx, 1073741824 ; 40000000H call ??_U@YAPEAX_K@Z ; operator new[] mov QWORD PTR $T1[rbp], rax mov rax, QWORD PTR $T1[rbp] mov QWORD PTR ptr$[rbp], rax Если я делаю её переменной, или вообще выношу значение в другую единицу трансляции (т.е. вызываю new char[get_size()]), то всё становится корректно, т.к. аргумент начинает передаваться через rcx: ; 13 : char* ptr = new char[total]; mov rcx, QWORD PTR total$[rbp] call ??_U@YAPEAX_K@Z ; operator new[] mov QWORD PTR $T1[rbp], rax mov rax, QWORD PTR $T1[rbp] mov QWORD PTR ptr$[rbp], rax Выглядит как баг какой-то. Добавлено Да, это, похоже, баг самого посленего msvc 2019: https://godbolt.org/z/1f1hTv |
Сообщ.
#14
,
|
|
|
Баг-репорт написал?
|
Сообщ.
#15
,
|
|
|
Цитата OpenGL @ то в operator new[] аргумент передаётся через ecx Однако ж! |
Сообщ.
#16
,
|
|
|
Цитата OpenGL @ В общем, почему-то если size_t константа (компилил в дебаге с выключенной оптимизацией), то в operator new[] аргумент передаётся через ecx, так что неудивительно, что 8-байтовое целое урезается а если тип сделать __int64? |
Сообщ.
#17
,
|
|
|
Вообщем size_t или __int64 роли не играет, без const все работает корректно.
|
Сообщ.
#18
,
|
|
|
Цитата Qraizer @ Баг-репорт написал? Пока нет. Вечером напишу. |