CopyMemory

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

CopyMemory

Сообщение Конь » 21.07.2007 (Сб) 21:24

Не знаю, по какой формулировке идти в поиск...

Код: Выделить всё
    Dim bInfo(2047) As Byte
    Dim i As Integer
   
    Open FileName For Binary As #1
   
    For i = 0 To 39
        Get #1, , bInfo
        CopyMemory tInfo(i), bInfo(0), 2048
    Next
   
    Close #1

При первом же CopyMemory вылетает программа... Причем иногда работает, а иногда вылетает... Помогите, пожалуйста, разобраться, я с этой функцией второй раз в жизни работаю :)
Здесь tInfo - аргумент функции, динамический массив пользовательского типа. Каждый элемент массива занимает в памяти ровно 2048 байтов... Передаю всегда функции массив Info(39).

P.S.: Мож там надо писать не 2048, а 2047, но это не влияет на результат. Вылетает.
Подпись находится в стадии разработки...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 21.07.2007 (Сб) 21:28

Покажи код целиком.
Изображение

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 21:33

Код: Выделить всё

Public Type CMLA2PDB_UserInfo
    NickName As String * 16 '0
    PlayerName As String * 16 '1
    Phone As String * 16 '2
    Age As Integer '3
    Level As Integer '4
    Class As String * 32 '5
    Helmet As String * 32 '6
    Upper As String * 32 '7
    Lower As String * 32 '8
    Gloves As String * 32 '9
    Boots As String * 32 '10
    LeftHand As String * 32 '11
    RightHand As String * 32 '12
    Head As String * 32 '13
    Necklare As String * 32 '14
    Earring1 As String * 32 '15
    Earring2 As String * 32 '16
    Ring1 As String * 32 '17
    Ring2 As String * 32 '18
    Future As String * 526 '19
End Type

Dim Info(39) As CMLA2PDB_UserInfo

Private Sub ReadDB(tInfo() As CMLA2PDB_UserInfo, DB As String)

    Dim bInfo(2047) As Byte
    Dim i As Integer
   
    Open DB For Binary As #1
   
    For i = 0 To 39
        Get #1, , bInfo
        CopyMemory tInfo(i), bInfo(0), 2048
    Next
   
    Close #1

End Sub


Делаю для друга игрушку для контроля игроков в линейке ;)
Примитив. Такое ощущение, что я что-то где-то не так с массивами поступаю... Наверняка туплю и очень сильно :)
Подпись находится в стадии разработки...

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 21.07.2007 (Сб) 21:44

Может, последнм параметром CopyMemory передавать Len(tInfo(i)), да и размерность байтового массива так задавать.
Это раз. Во вторых в файле строки что, в юникоде? Если нет, то читать надо непосредственно элемент структуры.
Изображение

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 21:47

Ну нифига себе, работает
Подпись находится в стадии разработки...

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 21:48

keks-n
"читать непосредственно элемент структуры" - это как? не въезжаю.
Подпись находится в стадии разработки...

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

Сообщение Хакер » 21.07.2007 (Сб) 21:50

Конь
Для чего читать по-элементно в массив, а потому копировать всё это в байтовый массив?

Не судьба прочитать всё сразу в байтовый массив?

Или данные в байтовом массиве должны иметь отчасти юникодный характер?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 21:54

Хакер
И то правда... У меня мозги начали клинить после полугода отсутствия программирования :)
Подпись находится в стадии разработки...

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 22:08

Что ему может не нравиться в строке
Код: Выделить всё
Len(tInfo(0)) * 40

?
Len(tInfo(0)) он четко возвращает - 1026. А на это выдает Overflow. Странно.
Подпись находится в стадии разработки...

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

Сообщение Хакер » 21.07.2007 (Сб) 22:10

40& вместо 40
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 23:50

А теперь снова вылетает :)
Строка CopyMemory bInfo(0), tInfo(0), Len(tInfo(0)) * 40&.
Я уже вообще под столом потихоньку засыпаю... :)
Подпись находится в стадии разработки...

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

Сообщение Хакер » 21.07.2007 (Сб) 23:53

Ещё раз: показывай весь код, с учётом деклараций.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 21.07.2007 (Сб) 23:58

Код: Выделить всё
Public Type CMLA2PDB_UserInfo
    NickName As String * 16 '0
    PlayerName As String * 16 '1
    Phone As String * 16 '2
    Age As Integer '3
    Level As Integer '4
    Class As String * 32 '5
    Helmet As String * 32 '6
    Upper As String * 32 '7
    Lower As String * 32 '8
    Gloves As String * 32 '9
    Boots As String * 32 '10
    LeftHand As String * 32 '11
    RightHand As String * 32 '12
    Head As String * 32 '13
    Necklare As String * 32 '14
    Earring1 As String * 32 '15
    Earring2 As String * 32 '16
    Ring1 As String * 32 '17
    Ring2 As String * 32 '18
    Future As String * 526 '19
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Public Info(39) As CMLA2PDB_UserInfo

Private Sub ReadDB(tInfo() As CMLA2PDB_UserInfo, DB As String)

    Dim bInfo(81919) As Byte
   
    Open DB For Binary As #1
   
    Get #1, , bInfo
    CopyMemory tInfo(0), bInfo(0), Len(tInfo(0)) * 40&
   
    Close #1

End Sub


Или уже правда пойти выспаться? :))
Подпись находится в стадии разработки...

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 22.07.2007 (Вс) 0:06

Код: Выделить всё
Public Type CMLA2PDB_UserInfo
    NickName As String * 16 '0
    PlayerName As String * 16 '1
    Phone As String * 16 '2
    Age As Integer '3
    Level As Integer '4
    Class As String * 32 '5
    Helmet As String * 32 '6
    Upper As String * 32 '7
    Lower As String * 32 '8
    Gloves As String * 32 '9
    Boots As String * 32 '10
    LeftHand As String * 32 '11
    RightHand As String * 32 '12
    Head As String * 32 '13
    Necklare As String * 32 '14
    Earring1 As String * 32 '15
    Earring2 As String * 32 '16
    Ring1 As String * 32 '17
    Ring2 As String * 32 '18
    Future As String * 526 '19
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Public Info(39) As CMLA2PDB_UserInfo

Private Sub ReadDB(tInfo() As CMLA2PDB_UserInfo, DB As String)

    Dim bInfo(81919) As Byte
   
    Open DB For Binary As #1
   
    Get #1, , bInfo
    CopyMemory tInfo(lbound(tInfo)), bInfo(lbound(bInfo)), Len(tInfo(0)) * (ubound(tInfo)-lbound(tInfo)+1)
   
    Close #1

End Sub


Это вообще, на будущее; но уверен ли ты, что *526, а не *256?
Последний раз редактировалось GSerg 22.07.2007 (Вс) 0:14, всего редактировалось 1 раз.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 22.07.2007 (Вс) 0:12

GSerg
Вылетает ;)
С LBound и UBound не стоит заморачиваться, LBound - всегда 0, UBound - всегда 39...
526 там из-за того, чтоб округлить это все дело до 2048 байтов...
Последний раз редактировалось Конь 22.07.2007 (Вс) 0:16, всего редактировалось 1 раз.
Подпись находится в стадии разработки...

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 22.07.2007 (Вс) 0:15

GSerg писал(а):но уверен ли ты, что *526, а не *256?
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 22.07.2007 (Вс) 0:17

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

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

Сообщение Хакер » 22.07.2007 (Вс) 0:20

:roll: Ты вообще что-ли не понимаешь, что делаешь?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 22.07.2007 (Вс) 0:23

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

Конь
Постоялец
Постоялец
 
Сообщения: 650
Зарегистрирован: 02.06.2006 (Пт) 6:49
Откуда: г. Красноярск

Сообщение Конь » 22.07.2007 (Вс) 10:57

Хакер
Дай, пожалуйста, наводящий вопрос относительно того, чего я не понимаю... А то я не понимаю, что именно я не понимаю... :roll:
Подпись находится в стадии разработки...

VB-constructor
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 160
Зарегистрирован: 24.07.2006 (Пн) 21:37
Откуда: Ростов-на-Дону

Сообщение VB-constructor » 25.07.2007 (Ср) 18:48

вобщем так:
Код: Выделить всё
Option Explicit


Public Type CMLA2PDB_UserInfo
    NickName As String * 16 '0
    PlayerName As String * 16 '1
    Phone As String * 16 '2
    Age As Integer '3
    Level As Integer '4
    Class As String * 32 '5
    Helmet As String * 32 '6
    Upper As String * 32 '7
    Lower As String * 32 '8
    Gloves As String * 32 '9
    Boots As String * 32 '10
    LeftHand As String * 32 '11
    RightHand As String * 32 '12
    Head As String * 32 '13
    Necklare As String * 32 '14
    Earring1 As String * 32 '15
    Earring2 As String * 32 '16
    Ring1 As String * 32 '17
    Ring2 As String * 32 '18
    Future As String * 526 '19
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, _
pSrc As Any, ByVal ByteLen As Long)


Public Sub ReadDB(tInfo() As CMLA2PDB_UserInfo)

    Dim bInfo(40) As CMLA2PDB_UserInfo
   
    Dim l_BINF As Long: l_BINF = Len(bInfo(0))
   
    CopyMemory ByVal VarPtr(bInfo(0)), ByVal VarPtr(tInfo(0)), l_BINF * 40
   
    MsgBox bInfo(0).Age 'проверяем

End Sub


и обращаемся примерно так:
Код: Выделить всё
Option Explicit
Dim m(40) As CMLA2PDB_UserInfo

Private Sub Command1_Click()
    m(0).Age = 40
    ReadDB m
End Sub


но почему при Dim l_BINF As Long: l_BINF = Len(bInfo(0)) * 40 - возникает ошибка для меня загадка
Человек рождён для того, чтобы достичь жизни...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.07.2007 (Ср) 18:54

Известно почему: результат не влазит в Integer.
Изображение

VB-constructor
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 160
Зарегистрирован: 24.07.2006 (Пн) 21:37
Откуда: Ростов-на-Дону

Сообщение VB-constructor » 25.07.2007 (Ср) 19:00

так там ведь только Long :!:, если бы Integer - все было бы проще
Человек рождён для того, чтобы достичь жизни...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.07.2007 (Ср) 19:19

Код: Выделить всё
Debug.Print TypeName(Len(bInfo(0)))
Debug.Print TypeName(40)
Изображение

VB-constructor
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 160
Зарегистрирован: 24.07.2006 (Пн) 21:37
Откуда: Ростов-на-Дону

Сообщение VB-constructor » 25.07.2007 (Ср) 19:35

хм, и то верно :o

а я поверил и не проверил, что

Синтаксис

Len(string | varname)

Возвращает значение типа Long, содержащее число символов в строке или число байт, необходимое для размещения переменной. Из двух возможных аргументов должен быть указан один (и только один). Для определяемых пользователем типов (UDT) функция возвращает размер, который требуется для записи переменной в файл.
Человек рождён для того, чтобы достичь жизни...

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 26.07.2007 (Чт) 12:25

Конь
Загнал бы эту инфу в класс, сделав функцию клонирования и не мучился. Тогда можно было бы сделать произвольную длинну строк. При необходимости сохранения - загонять всё в PropertyBag
Изображение


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

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

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

    TopList