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

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

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

Сообщение arthur2 » 27.02.2014 (Чт) 4:43

Собственно, вопрос к Хакеру :)

Два года назад вот в этой теме в оффтопе было интересное обсуждение по поводу использования массивов как указателей:
viewtopic.php?p=6762830#p6762830

arthur2 писал(а):Кстати, а чем отличается статический массив от динамического? Я имею ввиду изнутри - SAFEARRAY. Это я к тому. что где тебе нужен указатель на одну структуру, ты объявляешь статические массивы из одного члена, а где нужно двигать указатель, объявляешь его как динамический массив и редимишь.


Проделал такой тест:
Код: Выделить всё
Public Sub testSaMap()
    Dim m(0) As myType ': ReDim m(0)
   
    Dim s As String: s = Space$(50)
   
    SaMap AryPtr(m), StrPtr(s), 100
    Debug.Print m(1).a
     Stop
   
    Mid$(s, 1, 10) = "0123456789"
    Debug.Print m(1).a
     Stop
   
    SaUnmap AryPtr(m)

End Sub
Получилось, что статический массив вполне нормально редимится ручками :) Понятно, что ты выбрал именно динамический массив не просто так. Так в чём же грабли?
Артур
 
   

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

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

Сообщение Хакер » 27.02.2014 (Чт) 5:43

arthur2 писал(а):Так в чём же грабли?

Главным образом: SA-дескриптор не используется для контроля границ. Всегда используются жестко вшитые в код константы.
Возможно ещё была причина, но я сейчас не помню.
—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 » 27.02.2014 (Чт) 6:04

Хакер писал(а):SA-дескриптор не используется для контроля границ.
Кем - бейсиком? А если массив динамический, ты ведь всё равно сам подменяешь размер, так что всё равно самому надо контролировать границы. Или я не так понял?

Хакер писал(а):Всегда используются жестко вшитые в код константы.
Какие именно? ведь адрес данных и размер массива ты подменяешь, значит они не вшиты? А другие константы или значения, вроде бы, не используются, так что какая разница?


Хакер писал(а):Возможно ещё была причина, но я сейчас не помню.
Жаль... Эх, надо было мне тогда дожать свой вопрос
Артур
 
   

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

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

Сообщение Хакер » 27.02.2014 (Чт) 6:11

arthur2 писал(а):Кем - бейсиком? А если массив динамический, ты ведь всё равно сам подменяешь размер, так что всё равно самому надо контролировать границы. Или я не так понял?


Там у SaMap есть опциональный параметр, который означает границу. Для общего случая я туда поставил 0xFFFFFFFF — то есть преднамеренно очень большое значение, чтобы иметь возможность обращаться по произвольному смещению относительно новоустановленной базы.

С fixed-size-массивом я никогда не смогу обратиться по произвольному смещению (смещение будет сравнено с границами, использованными при объявлении массива, а не теми, что хранятся в SA-дескрипторе). Кроме случая, когда в настройках оптимизации проверка границ будет вообще выключена.

То есть если массив был объявлен как Dim ptr(0) as long, то я не смогу взять ptr(666).
—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 » 27.02.2014 (Чт) 6:16

Хакер писал(а):То есть если массив был объявлен как Dim ptr(0) as long, то я не смогу взять ptr(666)
Так я же беру... Или мой код просто как надо не скомпилируетя? Сейчас попробую
Артур
 
   

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

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

Сообщение Хакер » 27.02.2014 (Чт) 6:18

У тебя myType там какой-то. С элементарными типами твой код тоже работает?
—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 » 27.02.2014 (Чт) 6:40

Да
Код: Выделить всё
Public Sub testSaMap2()
    Dim m(0) As Long ': ReDim m(0)
   
    Dim s As String: s = Space$(50)
   
    SaMap AryPtr(m), StrPtr(s), 100
    Debug.Print Hex(m(3))
     Stop
   
    Mid$(s, 1, 10) = "0123456789"
    Debug.Print Hex(m(3))
     Stop
   
    SaUnmap AryPtr(m)
   
   

End Sub
Артур
 
   

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

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

Сообщение Хакер » 27.02.2014 (Чт) 6:42

В скомпилированном виде работает? И в Native-код и в P-код?
—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 » 27.02.2014 (Чт) 6:46

После компиляции не работает :(
Артур
 
   

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

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

Сообщение Хакер » 27.02.2014 (Чт) 6:53

Ну вот видишь.
—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 » 27.02.2014 (Чт) 6:53

Ещё вопрос вдогонку: у тебя в SaUnmap вместо адреса и размера вписываются не предыдущие значения, а нули. Это не чревато тем, что память, выделенная при редиме, останется подвешенной? Как вообще массив уничтожается бейсиком при выходе из процедуры? И можно ли SaМap натравливать на глобальные массивы - или только на те, что объявлены внутри процедур?
Артур
 
   

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

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

Сообщение Хакер » 27.02.2014 (Чт) 7:05

Откуда взяты SaMap и SaUnmap?
—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 » 27.02.2014 (Чт) 7:14

У тебя. Точнее не помню :)
Код: Выделить всё
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 » 27.02.2014 (Чт) 10:22

И ещё вдогонку: нужно ли вообще SaUnmap для фиксированного массива?
Артур
 
   

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

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

Сообщение ger_kar » 27.02.2014 (Чт) 15:57

arthur2 писал(а):И ещё вдогонку: нужно ли вообще SaUnmap для фиксированного массива?
Смотря какого, если это локальная переменная, то она и без SaUnmap хорошо обойдется, а точнее SaUnmap там вообще никак не нужен ни для статического массива, не для динамического. А вот если переменная уровня модуля тогда нужно смотреть, что-бы с одной стороны не допустить утечек памяти, а с другой не привести к освобождению еще нужного участка памяти.
Бороться и искать, найти и перепрятать

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

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

Сообщение Хакер » 28.02.2014 (Пт) 8:55

ger_kar, ерунду говоришь.

Позже распишу, что и как.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

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

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

Сообщение ger_kar » 28.02.2014 (Пт) 9:11

А что тут не так? Место для локальной переменной выделится в стеке и при выходе из процедуры ничего освобождать не нужно, а раз так, то и SaUnmap не нужен.
Бороться и искать, найти и перепрятать

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

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

Сообщение Хакер » 28.02.2014 (Пт) 11:14

Место под ячейки массива выделяется в стеке? :roll:
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

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

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

Сообщение ger_kar » 28.02.2014 (Пт) 15:33

Провел небольшой опыт, оказалось, что даже для статического массива память выделяется совсем не в стеке :( .
Бороться и искать, найти и перепрятать

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

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

Сообщение Хакер » 28.02.2014 (Пт) 15:42

Да что вам этот статический, статический это вообще самый нетривиальный случай.
—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 » 02.03.2014 (Вс) 12:45

Как я себе представлял ситуацию: при создании массива на уровне процедуры в стеке выделяется место только под указатель на SA. То есть, четыре байта. Под саму SA память выделяется в каком-то произвольном (по меньшей мере, не важно в каком) месте. Под данные массива память выделяется ещё в каком-то месте. Причем, для статического сразу при вызове процедуры, а для динамических - при редиме.

При выходе из процедуры сначала уничтожаются данные - по адресу из SA. Так как этот адрес мы подменяли, нам нужно вписать туда либо то, что было, либо ноль. Если вписываем ноль, значит данные вообще не уничтожаются, так? То есть, то, что выделено редимом, должно остаться висеть.

Раз ты вписываешь в SA именно ноль, а не старый адрес, значит, мои представления, вероятно, были не верны. Тогда получается, что уничтожение данных происходит без использования информации из SA? По меньшей мере, для фиксированных массивов. Поэтому я и предположил, что для них размапливать не обязательно. Или это по-разному под ИДЕ и в релизе?

В общем, пока получилось противоречие: если при уничтожении данных адрес из SA используется, то почему мы туда пишем 0, а не прошлый адрес? ведь тогда память, изначально выделенная под массив, не освободится. Если при уничтожении данных адрес из SA не используется (просто как-то хитро уничтожается именно то, что выделено), то зачем вообще размапливать уничтожаемую SA?

И вот ещё что очень интересно:
Потому что я хочу сделать классный кирпич, в котором вместо SaMap — какая-нибудь функция с другим более понятным называнием, а вызывать SaUnmap (про вызов которого если забыть — будт утечка памяти) будет вообще не нужно, потому что SaUnmap будет вызываться автоматически при выходе из процедуры, и в котором не нужно будет вызывать AryPtr.
Как в принципе ты планировал добиться того, чтобы при выходе из процедуры что-то вызывалось?
Последний раз редактировалось arthur2 02.03.2014 (Вс) 13:37, всего редактировалось 2 раз(а).
Артур
 
   

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

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

Сообщение ger_kar » 02.03.2014 (Вс) 12:52

arthur2 писал(а):Как я себе представлял ситуацию: при создании массива на уровне модуля в стеке выделяется место только под указатель на SA. То есть, четыре байта.
Так происходит только для локальной переменной уровня процедуры, именно под такие переменные выделяется место в стеке. Что касается переменных уровня модуля, то они находятся не в стеке.
Бороться и искать, найти и перепрятать

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

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

Сообщение arthur2 » 02.03.2014 (Вс) 13:27

Это описка - "на уровне модуля" я как раз и имел ввиду на уровне процедуры. Что, собственно, понятно из контекста того, что я дальше спрашиваю.
Артур
 
   

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

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

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

arthur2 писал(а):В общем, пока получилось противоречие: если при уничтожении данных адрес из SA используется, то почему мы туда пишем 0, а не прошлый адрес? ведь тогда память, изначально выделенная под массив, не освободится. Если при уничтожении данных адрес из SA не используется (просто как-то хитро уничтожается именно то, что выделено), то зачем вообще размапливать уничтожаемую SA?
Ну вообще идея следующая. Все зависит от того, что и для чего мапится. Например была выделена память под некую структуру, затем к этому участку примапили массив и поработали с ним. Далее вызывается SaUnmap и массив отмонтируется от этого участка. Если это был фиксированный массив то его уничтожать не требуется, а значение адреса в SA можно просто занулить. Но сам SaUnmap нужен для того, что-бы не освободить память к которой был примонтирован массив. Ибо она как правило и выделяется и освобождается совсем в другом месте. А иначе может получится так, что при уничтожении массива эта память будет освобождена, даже если она и нужна, а сама структура например может использоваться и далее в других местах. А вот если массив динамический, то нужно не занулять, а прописывать старый адрес. Но если делать универсальные функции, то лучше всегда прописывать старый адрес.
Бороться и искать, найти и перепрятать

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

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

Сообщение arthur2 » 02.03.2014 (Вс) 14:36

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

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

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

Сообщение ger_kar » 02.03.2014 (Вс) 14:56

arthur2 писал(а):Раз у Хакера прописываются именно нули, значит наверное так можно. Вот и хочется понять, как всё на самом деле, раз можно старые адреса не хранить.
Ну это исключительно частный случай. А для того чтобы не было парок с хранением старого адреса, можно процедуры вынести в отдельный модуль и адрес хранить в переменной этого модуля. Все будет хорошо и компактно. А если предполагается мапить несколько массивов, то тогда лучше модуль класса заюзать.
Бороться и искать, найти и перепрятать

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

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

Сообщение arthur2 » 02.03.2014 (Вс) 15:25

Кстати, SA фиксированного массива выделяется, я так понял, всё же в стеке. По крайней мере, адрес SA недалеко от адреса указателя на SA:

Код: Выделить всё
    Dim ppSa As Long, psa As Long
   
    Dim m(0) As myType
    ppSa = AryPtr(m)
    GetMem4 ppSa, psa
   
    MsgBox "Фиксированный массив:" & vbCrLf & vbCrLf & _
           Hex(ppSa) & "  ppSa" & vbCrLf & _
           Hex(psa) & "  pSa" & vbCrLf & _
           Hex(Not (Not (m))) & "  not(not)"
   
    Dim t() As myType: ReDim t(0)
    ppSa = AryPtr(t)
    GetMem4 ppSa, psa
   
    MsgBox "Динамический массив:" & vbCrLf & vbCrLf & _
           Hex(ppSa) & "  ppSa" & vbCrLf & _
           Hex(psa) & "  pSa" & vbCrLf & _
           Hex(Not (Not (t))) & "  not(not)"

И, судя по тому, что нот-нот возвращает таки не AryPtr, а адрес SA, то в SaMap/SaUpmap можно обойтись вообще без AryPtr и ppSa: передавать им сразу not(not(arrey)) (особенно учитывая, что нот-нот сразу компилируется в число)
Артур
 
   

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

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

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

ger_kar писал(а):Ну это исключительно частный случай.
Судя по тому, что Хакер предлагал сжигать тех, кто сознательно допускает утечки, как-то сомнительно, что это именно частный случай. Особенно учитывая, что код из одного из его кирпичей.
ger_kar писал(а): А если предполагается мапить несколько массивов, то тогда лучше модуль класса заюзать.
Если предполагается мапить один-единственный массив, то мапить его следует на месте, без лишних процедур. А если для большого количества массивов-указателей городить классы (а в них ещё вписать все необходимые проверки, которых принципиально нет в наших Samap/saupmap), то вообще смысл всем этим пользоваться теряется.
Артур
 
   

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

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

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

arthur2 писал(а):И, судя по тому, что нот-нот возвращает таки не AryPtr, а адрес SA, то в SaMap/SaUpmap можно обойтись вообще без AryPtr и ppSa: передавать им сразу not(not(arrey)) (особенно учитывая, что нот-нот сразу компилируется в число)
Вот блин, нельзя, увы. Для динамического массива pSa и not(not(ar)) совпадает, но для фиксированного под иде тоже совпадает, а вот в релизе - уже не хочет :(
Артур
 
   

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

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

Сообщение ger_kar » 02.03.2014 (Вс) 16:13

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

След.

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

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

Сейчас этот форум просматривают: Majestic-12 [Bot] и гости: 12

    TopList  
cron