Массив как указатель

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 02.03.2014 (Вс) 16:49

Вот интересный ты. Думаешь, я выдрал эти две функции, не посмотрев, как они используются? Я бы тогда просто не понял, зачем они нужны. Ни какой "частности" этого случая в коде нет.

Раз это "частный случай", значит нужно понять, в чём, собственно, его частность. Если в этом частном случае утечек нет, то с чего они вдруг будут в не частном случае? Собственно, я ж для того и вопрос задаю.
Артур
 
   

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Массив как указатель

Сообщение ger_kar » 02.03.2014 (Вс) 17:09

arthur2 писал(а):Ни какой "частности" этого случая в коде нет.Раз это "частный случай", значит нужно понять, в чём, собственно, его частность. Если в этом частном случае утечек нет, то с чего они вдруг будут в не частном случае? Собственно, я ж для того и вопрос задаю.
Давай тогда уточним. Речь идет про кирпич "Создание объектов по имени класса"? Если да, то тогда я тоже про него.
Начнем с того, а для чего там используется монтирование массива? Ответ очевиден, чтобы можно было работать с указателем на структуру, как с самой структурой. И это реализуется через нулевой элемент фиксированного массива с типом этой структуры. В этом и есть частный случай. Память выделяется при входе в процедуру и освобождается при выходе из неё. Будь это динамический массив, то это был бы уже другой случай.
Бороться и искать, найти и перепрятать

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Массив как указатель

Сообщение ger_kar » 02.03.2014 (Вс) 17:55

Что то у мене теперь тоже смутное сомнение, как мне кажется зануление указателя на первый элемент массива таки несмотря на фиксированный массив должен вызывать утечку памяти.
Бороться и искать, найти и перепрятать

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 02.03.2014 (Вс) 18:48

Да, кажется, из этого кирпича. И там ничуть не частный случай, а ровно тот случай, о котором я спрашиваю. И ровно то применение, которое я планирую для себя. А именно - использовать массивы в качестве указателей произвольного типа на произвольные данные.

Если ты внимательно посмотришь код, то увидишь, что у Хакера используются и динамические, и фиксированные массивы. Динамические - там, где нужно двигать указатель. Мало того, SaMap изначально содержит параметр, позволяющий задавать "размер массива" - как раз чтобы можно было сдвигать наш указатель на произвольную позицию. Мало того, я именно об разнице в применении таких указателей и спрашивал в первом же топике этой темы. Мало того, на эту часть вопроса Хакер уже ответил в этой теме более чем исчерпывающе. Мало того, в предыдущей теме (из которой и возник вопрос), он даже ответил и тебе по поводу моего вопроса:
Хакер писал(а):
ger_kar писал(а):Разница только в том,

Нет, разница в другом, касательно того аспекта, какой подметил Артур.
Правда, тогда так и не договорил. И сейчас что-то тоже долго подогревает интригу.
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 02.03.2014 (Вс) 21:23

Проделал такой фокус: определил первый параметр SaMap ByRef as long, а потом переопределил её помощью кирпича на byref ary() as any Теперь в процедуру сразу приходит pSa и не нужно AryPtr

Код: Выделить всё
Public Declare Sub SaMap Lib "*" _
      (Ary() As Any, ByVal pMemory As Long, Optional ByVal newSize As Long = &HFFFFFFFF)


Private Sub m_SaMap(ByRef pSA As Long, ByVal pMemory As Long,  ByVal newSize As Long = -1)
    'Dim pSA As Long: GetMem4 ppSA, pSA  Теперь эта строка и это действие не нужны
    PutMem4 pSA + 12, ByVal pMemory: PutMem4 pSA + 16, ByVal newSize
End Sub

Вроде, работает и с фиксированными, и с динамическими, и после компиляции :)
Последний раз редактировалось arthur2 02.03.2014 (Вс) 21:44, всего редактировалось 3 раз(а).
Артур
 
   

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Массив как указатель

Сообщение ger_kar » 02.03.2014 (Вс) 21:27

Ну работать то может и работает, а как насчет утечек?
Бороться и искать, найти и перепрятать

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 02.03.2014 (Вс) 21:34

Насчет обнуления адреса - ждем Хакера. Да и в любом случае - непонятки только с SaUpmap, к SaMap как раз вопросов нет. А то, про что я говорю "работает" - это как с помощью переопределения функции избавиться от AryPtr, а заодно и от ppSa.

Первое со вторым не связано :)
Артур
 
   

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Массив как указатель

Сообщение ger_kar » 02.03.2014 (Вс) 21:48

arthur2 писал(а):Насчет обнуления адреса - ждем Хакера.
Ну или как вариант - это посмотреть в отладчике и провести эксперименты.
Бороться и искать, найти и перепрятать

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 04.03.2014 (Вт) 12:14

Пользоваться отладчиком не умею. Какой эксперимент провести, чтобы проверить, освободилась ли память, мне в голову не приходит.

Хакер что-то долговато не появляется - пытаюсь пока преодолеть ступор. Переписал функции, чтобы SA выделялась и уничтожалась без участия бейсика:
Код: Выделить всё
Private Declare Sub SafeArrayAllocDescriptor Lib "oleaut32.dll" _
        (ByVal cDims As Long, ppsaOut As Any)
Private Declare Sub SafeArrayDestroyDescriptor Lib "oleaut32.dll" _
        (pSA As Any)
Код: Выделить всё
Private Sub mAryAsPtr _
             (ByVal ppSA As Long _
            , ByVal lnElm As Long _
            , ByVal pMem As Long _
            , Optional ByVal arySize As Long = 1)
       
       Dim pSA As Long
'присылаем всегда неинициированныq массив. Создаем всегда одномерный массив.
       SafeArrayAllocDescriptor 1, ByVal ppSA 'выделяем новый дескриптор массива и память под него
       GetMem4 ppSA, pSA 'получаем дескриптор SAFEARRAY
       PutMem4 pSA + 4, lnElm 'записываем размер элемента массива
       PutMem4 pSA + 12, pMem ' адрес данных
       PutMem4 pSA + 16, arrSyze ' длинну массива
End Sub

Private Sub mAryAsPtrFree(ByVal ppSA As Long)
  Dim pSA As Long
  GetMem4 ppSA, pSA
  SafeArrayDestroyDescriptor ByVal pSA
  PutMem4 ppSA, 0
End Sub
Теперь массив в процедуре не редимится, так что ничего освобождать, вроде не надо.
Артур
 
   

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Массив как указатель

Сообщение ger_kar » 04.03.2014 (Вт) 15:38

Ну и зачем такое нагромождение? Гораздо проще и удобнее запомнить старый адрес, а затем вернуть его обратно.

arthur2 писал(а):Какой эксперимент провести, чтобы проверить, освободилась ли память, мне в голову не приходит.

Элементарный - создавать, монтировать и совершать прочие манипуляции над массивом в цикле. Сделать массив структур, со структурами пожирнее ну и зашаращить побольше итераций, ну скажем штук этак 100000 :) Запустить цикл и наблюдать. Если память потечет, то это будет заметно невооруженным глазом в том же диспетчере задач.
Бороться и искать, найти и перепрятать

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 04.03.2014 (Вт) 15:53

ger_kar писал(а):Ну и зачем такое нагромождение? Гораздо проще и удобнее запомнить старый адрес, а затем вернуть его обратно.
Ну продемонстрируй - как запомнить старый адрес и при этом не нагромоздить :)

Ни какого нагромождения нет, и код, по сути, даже короче, чем был - поскольку внутри редима есть кроме SafeArrayAllocDescriptor ещё и SafeArrayAIIocData, причем память, выделенная нам под массив, нами вообще не используется. Вместо этого мы должны запомнить адрес этого ненужного нам куска, а потом ещё и вернуть его назад. Ну и где больше нагромождение?

На счёт сути проверки, течёт ли память - мысль хорошая... Кстати, а может для таких вещей есть какие-нибудь стандартные средства?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Массив как указатель

Сообщение Хакер » 04.03.2014 (Вт) 16:26

arthur2 писал(а):Хакер что-то долговато не появляется

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

Приведите наконец эксперимент. Ибо чую мне придётся идти конструировать печь для самосожжения.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 05.03.2014 (Ср) 19:11

Разгребайся и велком :)
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Массив как указатель

Сообщение Хакер » 05.03.2014 (Ср) 19:13

Ты проверил?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 05.03.2014 (Ср) 19:52

У меня тоже завал, правда, не глобальный :) Проверю, отпишусь
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 06.03.2014 (Чт) 6:26

В общем, сделал такой тест:
Код: Выделить всё
Private Declare Sub GetMem4 Lib "msvbvm60" (ByVal lpAddress As Long, dst As Any)
Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal lpAddress As Long, ByVal nv As Long)
Declare Function AryPtr Lib "MSVBVM60.DLL" Alias "VarPtr" (ary() As Any) As Long

Public Type myBigType
  b(&HFF00&) As Byte
End Type

Public exitFl As Boolean

Public Sub test()

Dim s As String * 10
Dim sPtr As Long: sPtr = StrPtr(s)

Dim i As Long
Do
    For i = 0 To 1000
        mTest sPtr
    Next
   
    DoEvents
    If exitFl Then Exit Sub
Loop
End Sub

Private Sub mTest(ByVal ptMem As Long)
Dim m() As myBigType
ReDim m(0)

SaMap AryPtr(m), ptMem
SaUnmap AryPtr(m)

End Sub

Public Sub SaMap(ByVal ppSA As Long, ByVal pMemory As Long, Optional ByVal NewSize As Long = -1)
    Dim pSA As Long: GetMem4 ppSA, pSA:
    PutMem4 pSA + 12, ByVal pMemory: PutMem4 pSA + 16, ByVal NewSize
End Sub

Public Sub SaUnmap(ByVal ppSA As Long)
    Dim pSA As Long: GetMem4 ppSA, pSA
    PutMem4 pSA + 12, ByVal 0: PutMem4 pSA + 16, ByVal 0
End Sub

Через некоторое время программа вываливается с аутом оф мемери :)
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 06.03.2014 (Чт) 6:44

Если старый адрес возвращать, то всё нормально:
Код: Выделить всё
Private Sub mTest(ByVal ptMem As Long)
Dim m() As myBigType
ReDim m(0)
Dim oldAdr As Long
oldAdr = SaMap(AryPtr(m), ptMem)
SaUnmap AryPtr(m), oldAdr

End Sub
Public Function SaMap(ByVal ppSA As Long, ByVal pMemory As Long, Optional ByVal NewSize As Long = -1) As Long
    Dim pSA As Long: GetMem4 ppSA, pSA:
    GetMem4 pSA + 12, SaMap
    PutMem4 pSA + 12, ByVal pMemory: PutMem4 pSA + 16, ByVal NewSize
End Function

Public Sub SaUnmap(ByVal ppSA As Long, ByVal oldAdr As Long)
    Dim pSA As Long: GetMem4 ppSA, pSA
    PutMem4 pSA + 12, ByVal oldAdr: PutMem4 pSA + 16, ByVal 1
End Sub
Артур
 
   

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Массив как указатель

Сообщение ger_kar » 06.03.2014 (Чт) 16:58

Ну вот и прояснилась ситуация, надо теперь в старых проектах, где юзались SaMap и SaUnMap произвести реформу и внедрить сохранение и возвращение старого адреса. Спасибо Артуру, что поднял этот вопрос.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Массив как указатель

Сообщение Хакер » 06.03.2014 (Чт) 23:19

Подождите, а в тех условиях, в которых SaMap применялся там, откуда вы его взяли, вы проверяли? Там же статический массив вроде в кирпиче?

Плюс, как производилась проверка? Должно быть три теста:
  • Под IDE
  • Скомп. в P-код
  • Скомп. в Native-код
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Массив как указатель

Сообщение arthur2 » 07.03.2014 (Пт) 5:19

В кирпиче есть и фиксированные, и динамический. К тому же, SaMap изначально нацелена прежде всего на динамические массивы (размер в параметре по умолчанию - максимально возможный) - эта тема же даже с вопроса по этому поводу начиналась.

Бейсик не дал мне объявить фиксированный массив со структурой размером под 64 кило, я и не стал заморачиваться, а объявил только динамический. Тест делал в скомпилированном в нативе экзешнике. А какой смысл проверять два других варианта, если этот уже обломился?

Сейчас сделал структуру помельче и переопределил массив на статический - программа так же вывалилась, только на этот раз молча. Ну и, понятно, ждать пришлось дольше.
Артур
 
   

Пред.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот, SemrushBot и гости: 51

    TopList