На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> оператор new выделение памяти больше 4Gb , new выделяет память, количество которой определяется переменной типа UINT
    Стандартный оператор new выделяет память не более 4 гигабайт. Существует ли возможность выделить больше памяти, может какая ни будь библиотека?
      Цитата a_n_y_a @
      Стандартный оператор new выделяет память не более 4 гигабайт.

      Откуда информация?
      Вот например почитай обсуждение: http://rsdn.org/forum/winapi/2786441.flat
      Там люди выделяют больше 4 гигабайт оператором new :-? Но наверное лучше воспользоваться VirtualAlloc, как советуют в обсуждении. И хорошо подумать - а дествительно памяти надо больше 4 гигов?
      Сообщение отредактировано: Wound -
        На другой компилятор перейти есть возможность? Например, вот это:
        ExpandedWrap disabled
          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 работает нормально, в студии - нет.
          Цитата OpenGL @
          в clang работает нормально, в студии - нет.
          ExpandedWrap disabled
            #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
          ExpandedWrap disabled
            8       000001180F591040
            az
            Странно. У меня в operator new[] приходит аргумент типа size_t, но усечённый до uint32_t, т.е. в данном случае 1 гигабайт. И поэтому падает всё. VS 2019.
              VS 2019
              Консольный в 64x
              размер size_t - 8

              16Гб оперативки (свободно 50%)
              Запускаем, выделение по диспетчеру 1Гб (1024,4), в программе ошибка доступа к последнему байту, указатель не нулевой.
              Сообщение отредактировано: Black_Dragon -
                Сам по себе new память не выделяет, он вызывает malloc.
                Значит, если есть ограничение, это ограничение malloc-a.
                Если всё-таки очень нужно использование new с очень большими объёмами,
                тогда можно попробовать new/delete перегрузить и использовать их вместе с VirtualAlloc/VirtualFree.
                  Цитата ЫукпШ @
                  Значит, если есть ограничение, это ограничение malloc-a.

                  Вряд ли. В данном случае именно в operator new[] уже приходит урезанное число. Позже проверю вызов с malloc
                    Цитата ЫукпШ @
                    Сам по себе new память не выделяет, он вызывает malloc.
                    В Стандарте это нигде не гарантируется. Более того, он содержит утверждения, что allocation functions и C memory allocations являются разными средствами, работающими с разными аренами, хотя и не запрещает реализацию первых посредством вторых
                      А что в стандарте не предусмотрено, что если ты столько не можешь, то вернуть нуль???
                      Мы то получаем валидный указатель, но на меньший объем...
                        Цитата Black_Dragon @
                        А что в стандарте не предусмотрено, что если ты столько не можешь, то вернуть нуль???
                        Мы то получаем валидный указатель, но на меньший объем...

                        Что-то тут не таку вас..
                        Когда у меня не получилось, мне вернули NULL вместо адреса.
                        я попробовал взять 2Г для x86 системы.
                        ---
                        А в целом всё получилось.
                        Исходник всзял у Qraizer-а почти без изменений.
                        Перегрузил new/delete чтобы следить за выделяемыми блоками.
                        Собирал всё в VS2008 Express, WinXP Home Sp3
                        Исходник:
                        Скрытый текст

                        ExpandedWrap disabled
                          // ---------------------------------------------------------------------------------
                          // Перегрузка операции 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("----- ^^^ -----"));
                          }


                        В итоге получилось так:
                        user posted image
                        Диагностика из Dbgview:
                        user posted image
                        За пределами "заборчика" - это работа старт-апа.
                        Сообщение отредактировано: ЫукпШ -
                          Цитата 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).
                            Ха. Посмотрел сейчас ассемлерный выхлоп, поигрался с исходником... В общем, почему-то если size_t константа (компилил в дебаге с выключенной оптимизацией), то в operator new[] аргумент передаётся через ecx, так что неудивительно, что 8-байтовое целое урезается:
                            ExpandedWrap disabled
                              ; 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:
                            ExpandedWrap disabled
                              ; 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
                            Сообщение отредактировано: OpenGL -
                              Баг-репорт написал?
                                Цитата OpenGL @
                                то в operator new[] аргумент передаётся через ecx

                                Однако ж! :)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0428 ]   [ 17 queries used ]   [ Generated: 19.04.24, 23:14 GMT ]