На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual Basic: Общие вопросы
Здесь обсуждаются вопросы по языку Visual Basic 1-6 (а так же по схожим языкам, как, например, PowerBASIC).
Вопросы по Visual Basic .NET (это который входит в состав Visual Studio 2002/2003/2005/2008+, для тех, кто не в курсе) обсуждаются в разделе .NET.

Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что Вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются. Студенты, вам сюда: ПОМОЩЬ СТУДЕНТАМ!
4. Используйте теги [ code=vba ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Формулируйте свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной (и более) давности, без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта user posted image FAQ Раздела user posted image Кладовка user posted image Наши Исходники user posted image API-Guide user posted image Поиск по Разделу user posted image MSDN Library Online user posted image Google

Ваше мнение о модераторах: user posted image SCINER, user posted image B.V.
Модераторы: SCINER, B.V.
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> Out of memory для одномерного массива Double - каждый раз разное? , Visual Basic v.6.0.
    В общем, решил проблему структурой с кучей массивов по 2^23.

    Задав похожие вопросы в других местах - люди ни на одном ПК не могли получить больше 2^27. Питон преуспел в этом больше всех.
      Цитата Сергей85 @
      люди ни на одном ПК не могли получить больше 2^27.

      227*8 = 1 Гб - для 32-битного приложения это нормально.
      А вот 223*8 - явно мало. Либо у тебя какие-то левые dll рубят все свободное АП на несколько малых кусков (что мало вероятно), либо ты сам со своими массивами где-то косячишь (что более вероятно). Все это можно легко проверить с помощью VMMap (запустить, сохранить отчет в txt и выложить сюда).
        Цитата leo @

        Косячит хренова тонна программистов, попробовавших ПРОСТО СОЗДАТЬ массив 2^25? Я уже пишу не от лица 1 человека, а от 10-ти.
          Private Sub Command1_Click()
          Dim s() As Double

          ReDim s(2 ^ 28)
          End Sub
          Прикреплённая картинка
          Прикреплённая картинка

          Прикреплённая картинка
          Прикреплённая картинка
          Сообщение отредактировано: Сергей85 -
            Картинки VMMap ты привел совершенно не информативные. На них даже параметр Free\Largest block не виден, не говоря уже о занятых адресах (нужно хотя бы прокрутить нижний список до перехода адресов с 0ххх.. на Хххх..., чтобы увидеть причину фрагментации АП). Но лучше не картинки приводить, а сохранить данные VMMap через File\Save as в формате mmp и выложить их сюда, чтобы можно было увидеть всю картину\карту распределения памяти

            Пример: в Excel 2002 пишу аналогичный макрос: массив 2^26 выделяет нормально, 2^27 - облом. Смотрю в VMMap и вижу причину - максимальный свободный блок составляет всего 688 Мб, прокручиваю адреса до перехода с 0ххх.. на Хххх.. и вижу, что причина в самом Excel.exe и прочих приблудах Office, которые грузятся по адресам ~300.. и рубят свободный блок АП ~1.4 Гб примерно пополам.

            Цитата Сергей85 @
            Косячит хренова тонна программистов, попробовавших ПРОСТО СОЗДАТЬ массив 2^25?

            Ты уж определись - 2^25 или 2^27, т.к. разница очень существенная

            Добавлено
            PS: Единственная полезная инфа от выложенных картинок - это то, что свободный размер памяти у тебя превышает 2 Гб. Это говорит о том, что в твоей проге включен доступ к 3-му гигабайту (LARGE_ADDRESS_AWARE). Тем более не понятно, чем этот 3-й Гб занят, т.к. никакие dll обычно в него не грузятся ...
            Сообщение отредактировано: leo -
              2^26.
              Прикреплённый файлПрикреплённый файлDesktop.zip (37,91 Кбайт, скачиваний: 102)
                Цитата Сергей85 @
                2^26

                Ну и ?
                В Project1 максимальный свободный блок памяти составляет 970 Мб, поэтому и "почему-то нет ошибки" при выделении 8*2^26 = 536 Мб.
                В vb6 максимальный блок равен 435 Мб (< 536 Мб), поэтому и происходит облом-с. Причина, как обычно, в дурных dll MS Office (в данном случае mso97rt.dll), которые норовят влезть по адресам вблизи 30000000H. Однако, хоть это и неприятно, но терпимо. Ты же уверяешь, что у тебя 2^24-2^25 не всегда выделяются, а это всего лишь 134-268 Мб - сколько еще нужно загрузить дурных dll, чтобы они так раздробили всё адресное пространство?! Можешь выложить пример, где с выделением 2^24-2^25 происходит облом?

                Насчет 3-го Гб я ошибся - макс.объем свободной памяти в Project1 не превышает 2Гб. Поэтому кардинальным решением проблемы в 64-битных ОС может быть разрешение для твоей программы использовать 3-й Гб (опция LARGE_ADRESS_AWARE). Это можно сделать с помощью утилиты editbin.exe, которая должна входить в состав VC6 (см. первый попавшийся пример).
                  ExpandedWrap disabled
                    Option Explicit
                    Option Compare Text
                     
                    Dim oExcelApp As New Excel.Application  'Приложение.
                    Dim oDocExcel As New Excel.Workbook 'Документ Excel.
                    Dim oExWs As New Excel.Worksheet 'Таблица документа Excel.
                     
                    Dim g_bCancel As Boolean 'Отмена ресурсоемкого процесса.
                    Dim g_bCommand_Check_Click_Loaded As Boolean 'Самая ресурсоемкая функция завершила работу и успешно закрыла все приложения.
                     
                    Private Declare Function InitCommonControls Lib "Comctl32.dll" () As Long 'Для корректной загрузки COMCTL32.OCX в Windows XP.
                    Private Declare Function GetDesktopWindow Lib "user32" () As Long
                    Private Declare Function ShellExecute& Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long)
                    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long) 'Мгновенное копирование массивов.
                     
                     
                     
                     
                    Private Sub Command_Check_Click()
                    1 On Error GoTo ErrorHandler
                     
                    'Составление и заполнение массива данных.
                    3 Dim dNumbers_Array() As Double, dFormula_Array() As Double
                     
                     
                       'Открытие файла со списком номиналов.
                    20 g_oCommonDialog.FileName = ""
                    21 g_oCommonDialog.DialogTitle = "Открыть файл .XLS*"
                    22 g_oCommonDialog.Filter = "Файлы Microsoft Excel|*.xls*; *.csv"
                    23 If g_oCommonDialog.ShowOpen(Me) <> 0 Then Exit Sub
                    24 g_oCommonDialog.InitDir = g_oFSO.GetParentFolderName(g_oCommonDialog.FileName)
                     
                       'Создать приложение Excel и скрытно работать с документом.
                    42 Set oExcelApp = New Excel.Application
                    43 oExcelApp.Visible = False
                    44 oExcelApp.IgnoreRemoteRequests = True
                    45 Set oDocExcel = oExcelApp.Workbooks.Open(g_oCommonDialog.FileName, , True)
                    46 Set oExWs = oDocExcel.ActiveSheet
                     
                       'Работа построчно с передачей значений в функцию с формулами расчета. Количество комбинаций чисел - 2^n, что позволяет отказаться от факториалов и биномиального коэффициента.
                    47 While oExWs.Cells(lRow + 1, 1) <> ""
                    48     ReDim dNumbers_Array(0) 'Максимум чисел - 25.
                     
                    49     dMaximum_Number = 0
                    50     iCol = 0
                    51     g_sTemp = ""
                        
                    52     While oExWs.Cells(lRow + 1, iCol + 1) <> ""
                    53         If IsNumeric(oExWs.Cells(lRow + 1, iCol + 1)) Then
                    54             If iCol > 0 Then ReDim Preserve dNumbers_Array(iCol)
                    55             dNumbers_Array(iCol) = oExWs.Cells(lRow + 1, iCol + 1)
                    56             g_sTemp = g_sTemp & dNumbers_Array(iCol) & " "
                    57             If dMaximum_Number < dNumbers_Array(iCol) Then dMaximum_Number = dNumbers_Array(iCol)
                    58         Else
                    59             MsgBox "Ошибка: в строке " & lRow + 1 & " стоблце " & iCol & " указано не положительное число. Операция прервана, результаты на экране."
                    60             GoTo endd
                    61         End If
                     
                    62         iCol = iCol + 1
                    63     Wend
                        
                    64     [B]ReDim dFormula_Array(2 ^ (UBound(dNumbers_Array) + 1) - 2) 'Значение "все нули" не используется.[/B]


                  Добавлено
                  Не понимаю, как LARGE_ADRESS_AWARE подключается? По примеру фигня какая-то. Ведь получается, что проект должен вызвать editbin сам на себя.
                    Используя небольшую хитрость на 64 битных системах можно выделить больше 4ГБ памяти.
                      Цитата TheTrik @


                      Иииии?..
                        Цитата Сергей85 @
                        Иииии?..

                        Учитывая что любой процесс в 64 битной среде является 64 битным, включая 32 битные то мы можем использовать все преимущества 64 битного режима из 32 битного процесса. Именно для выделения памяти нужно переключится в 64 битный режим, найти ntdll, найти функцию NtAllocateVirtualMemory, вызвать ее, получить указатель в 64 битном пространстве, переключится обратно. Писать/читать либо переключаясь в 64 битный режим либо с помощью функций NtWow64WriteVirtualMemory64/NtWow64ReadVirtualMemory64.
                          Цитата Сергей85 @
                          Не понимаю, как LARGE_ADRESS_AWARE подключается?

                          LARGE_ADRESS_AWARE подключается путем простой установки флага в заголовке exe-файла. В продвинутых компиляторах это делается путем задания соответствующей опции линкера. В vb6 такой возможности нет. Поэтому нужно использовать утилиту editbin.exe, которая установит нужный флаг в уже готовом\скомпилированном экзешнике. Для этого нужно в винде выполнить команду "путь\editbin.exe /largeaddressaware путь\имя_твоей_проги.exe". Чтобы каждый раз не набирать эту абру-кадабру, можно в папке с твоей программой создать либо bat-файл (простой текстовый файл с расширением bat) с соответствующей строкой, либо ярлык для editbin.exe, в котором через Свойства изменить строку Объект - добавить " /largeaddressaware имя_твоей_проги.exe". А чтобы не забыть про все это дело, можно в проге добавить вызов функции GlobalMemoryStatusEx (как рекомендовано в примере) с выдачей предупреждения в случае ullTotalVirtual <= 2 Гб.
                            Замечания по коду #23.
                            1) Тебе уже в соседней ветке указали на то, что объявлять переменные oExcelApp, oDocExcel и oExWs через New не нужно, т.к. во-первых, это не имеет смысла, поскольку в Command_Check_Click ты их все равно устанавливаешь заново, во-вторых, создание Excel.Workbook и Worksheet через New может приводить к той самой ошибке 429 - "ActiveX component can't create object".
                            2) Я уже говорил, что вызов диалога открытия файла подгружает кучу разных dll (в том числе и совершенно левых, отвечающих за опции контекстного меню файла) и создает несколько потоков - все это может негативно сказываться на фрагментации адресного пространства твоей проги. Работа с объектами Excel также может приводить к подгрузке офисных dll, созданию расшареных регионов памяти и т.п. Поэтому, раз у тебя максимальный размер массива dFormula_Array не может превышать 2^25*8 = 268 Мб (по сути - это "мелочь пузатая"), то лучше выделить память под него сразу при старте проги (до вызова диалога открытия файла и создания объектов Excel - например, в Form_Load). Если в Command_Check_Click окажется, что для массива нужно меньше памяти, то можно сделать ReDim для уменьшения его размера (только без Preserve - иначе м.б. облом!)

                            PS: Наращивать длину массива dNumbers_Array по одному элементу, когда их максимальное число не может превышать 25 - это как-то э-э-э, "не профессионально". Проще использовать статический массив (можно с запасом, например на 32 элемента), а реальное кол-во используемых элементов хранить в отдельной переменной типа dNumbers_Count As integer
                            Сообщение отредактировано: leo -
                              1) Пробовал с разными вариантами перетасовки New - ошибка не меняется.
                              2) Ясно.

                              PS: что быстрее: Ubound(Array) или int при указании в условиях цикла For? Мне скорость циклов важнее, чем скорость заполнения массива dNumbers.
                                Цитата Сергей85 @
                                что быстрее: Ubound(Array) или int при указании в условиях цикла For?

                                Теоретически int "быстрее", но практически в цикле For ты разницы не заметишь, т.к. при For верхний предел (по идее) должен вычисляться только один раз перед входом в цикл (а не на каждой итерации как в while и do..loop)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0894 ]   [ 21 queries used ]   [ Generated: 28.03.24, 19:12 GMT ]