Что нового

"память не может быть 'read'" после использования DllCall()

real_sm

Новичок
Сообщения
18
Репутация
1
Здравствуйте.

Есть некая DLL'ка и к ней инструкция. DLL скомпилирована в MS C++ 6.0. В библиотеке есть функция:

Код:
Get information of disk arrays
Declaration:
VINT vr_get_array_info (VINT array_index, vr_array_info_t* pinfo);
Description:
Application can fetch the information of one specific disk array, which is located
by index of all disk arrays in current system.
Input parameters:
VINT array_index :
Index to all disk arrays in system, specify which disk array.
vr_array_info_t *pinfo :
14
Pointer to a vr_array_info_t data structure to get the information
Return value:
VR_SUCCESS :
Get the information successfully.
VR_ERR_NOT_INITED :
Raid lib hasn’t been initialized.
VR_ERR_INVALID_INDEX :
The input index is invalid.
VR_ERR_INVALID_PARAM :
Input parameter is invalid: the pointer is NULL.

DLL Export Viewer так пишет об этой функции:

Код:
Function Name     : int __cdecl vr_get_array_info(int,struct _vr_array_info *)

Вот как выглядит этот _vr_array_info в хедере:

Код:
typedef struct _vr_array_info {
        VWORD status;  // current status of disk array
                        
        VBYTE raidType;// same as Disk_Array.raidType, but value 0xFF means
                        // a stand-alone disk. When it's a stand-alone disk,
                        // only arDevices[0] and diskNum has meaning, and diskNum should
                        // always be 1 .

        VBYTE diskNum;// count of valid arDevices[] members. 

        // Note: disk array maybe incomplete, i.e. , some disk in the array maybe missing, 
        //     corresponding device ptr arDevices[i]->pRealDevice should be NULL.
        
        VDWORD capacityLow;// (Unit: sector)
        VDWORD capacityHigh;// (Unit: sector)

        // following 8 bytes define the real-capcity (in sector) of every disk in array
        VDWORD realCapacityLow;        // (Unit: sector)
        VDWORD realCapacityHigh;       // (Unit: sector)


        VDWORD stripeSize; // valid when raid is raid0, raid5 or raid01, in Kbytes
        VDWORD blockSize; // valid when raid is RAID5, in Kbytes

        VBOOL  bNeedMigration; // the raid need migration
                               // only valid when raid0/raid5/matrixRaid
        VBOOL  bNeedInit;      // the raid need initialization, only valid for RAID5
        VBOOL  bOptimized;     // only for RAID5, this RAID5 access was optimized

         VBYTE systemDisk;     /* does the devices within this disk array 
                                  contain system files of current running OS ? 
                                   the probably value are:
                                   VR_DEVICE_NOT_SYS_DISK
                                   VR_DEVICE_MAYBE_SYS_DISK
                                   VR_DEVICE_SYS_DISK
                                 they are defined in this file */

        VWORD raid_index;// only raid index, no meaning with stand-alone disk
        VINT  index; // all device index, including all raid and stand-alone disk
} vr_array_info_t;

А вот мой код (функции в библиотеке decorated, поэтому так странно выглядят в коде):

Код:
Local $pTest

$hDLL = DllOpen(@ScriptDir & "\drvInterface.dll")

;~ VINT vr_init (void);
ConsoleWrite("vr_init..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_init@@YAHXZ")

;~ VINT vr_get_controller_num (VINT *pnumber);
ConsoleWrite("vr_get_controller_num..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_controller_num@@YAHPAH@Z", "int*", "$pTest")
$iControllerNumber = $sTest[1]
ConsoleWrite("$iControllerNumber = " & $iControllerNumber & @CRLF)

;~ VINT vr_get_device_num (VINT *pnumber);
ConsoleWrite("vr_get_device_num..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_device_num@@YAHPAH@Z", "int*", "$pTest")
$iDeviceNumber = $sTest[1]
ConsoleWrite("$iDeviceNumber = " & $iDeviceNumber & @CRLF)

;~ VINT vr_get_array_num (VINT only_raid, VINT *pnumber);
ConsoleWrite("vr_get_array_num..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_num@@YAHHPAH@Z", "int", 0, "int*", "$pTest")
$iArrayNumber = $sTest[2]
ConsoleWrite("$iArrayNumber = " & $iArrayNumber & @CRLF)

$vr_array_info = DllStructCreate("ushort status;byte raidType;byte diskNum;dword capacityLow;dword capacityHigh;dword stripeSize;dword blockSize;boolean bNeedMigration;boolean bNeedInit;boolean bOptimized;byte systemDisk;byte raid_index;int index")
;~ VINT vr_get_array_info (VINT array_index, vr_array_info_t* pinfo);
ConsoleWrite("vr_get_array_info..." & @CRLF)
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_info@@YAHHPAU_vr_array_info@@@Z", "int", 0, "struct*", $vr_array_info)

;~ void vr_exit (void);
ConsoleWrite("vr_exit..." & @CRLF)
$sTest = DllCall($hDLL, "none", "?vr_exit@@YAXXZ")

DllClose($hDLL)

Exit


Все работает как полагается вплоть до вызова vr_get_array_info. По вызову vr_get_array_info AutoIt3.exe вызывает ошибку "память не может быть 'read'" ("Инструкция по адресу 0x7c93a514 обратилась к памяти по адресу 0x00000000"). При этом судя по консоли продолжает выполнение кода, но ошибка все равно всплывает.

Подскажите, пожалуйста, что я делаю не так?
 

Вложения

  • ProgGuide.pdf
    163.7 КБ · Просмотры: 1

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
real_sm
проблема не с библиотекой, а в
1. Операционной системе
2. Оперативной памяти
3. ... и так далее
В моей системе все функции выполняются
 
Автор
R

real_sm

Новичок
Сообщения
18
Репутация
1
joiner сказал(а):
real_sm
проблема не с библиотекой, а в
1. Операционной системе
2. Оперативной памяти
3. ... и так далее
В моей системе все функции выполняются

А у Вас тоже VIA RAID? Если нет, то библиотека на последнюю функцию Вам просто отвечает VR_ERR_INVALID_INDEX, спотыкаясь на первом аргументе (номер массива в RAID). До второго аргумента дело не доходит.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
real_sm
По-моему, в описании структуры $vr_array_info у вас пропущены realCapacityLow и realCapacityHigh. К тому же raid_index должен быть word, а не byte.

"struct*" я так понимаю - это указатель на структуру. Вероятно нужно передать
Код:
DllStructGetPtr($vr_array_info)


А для передачи переменной кавычки не нужны. Это я про "$pTest" в кавычках.
 
Автор
R

real_sm

Новичок
Сообщения
18
Репутация
1
InnI сказал(а):
real_sm
По-моему, в описании структуры $vr_array_info у вас пропущены realCapacityLow и realCapacityHigh. К тому же raid_index должен быть word, а не byte.

Веселые ребята в этом VIA работают. Вот как в PDF-ке:

Код:
vr_array_info_t
typedef struct _vr_array_info {
VWORD status;
VBYTE raidType; // value 0xFF means
// a stand-alone disk. When it's a stand-alone disk,
// only diskNum has meaning, and diskNum should
// always be 1 .
VBYTE diskNum;// count of valid disk members.
VDWORD capacityLow;// (Unit: sector)
VDWORD capacityHigh;// (Unit: sector)
VDWORD stripeSize; // valid when raid is raid0 or raid01, in Kbytes
VDWORD blockSize; // valid when raid is RAID5, in Kbytes
VBOOL bNeedMigration; // the raid need migration
// only valid when raid0/raid5/matrixRaid
VBOOL bNeedInit; // the raid need initialization, only valid for RAID5
VBOOL bOptimized; // only for RAID5, this RAID5 access was optimized
VBYTE systemDisk; /* does the devices within this disk array contain system
files of current running OS ? The probably value are:
VR_DEVICE_NOT_SYS_DISK
VR_DEVICE_MAYBE_SYS_DISK
VR_DEVICE_SYS_DISK
they are defined in this file */
VBYTE raid_index;// only raid index, no meaning with stand-alone disk
VINT index; // all device index, including all raid and stand-alone disk
} vr_array_info_t;


InnI сказал(а):
"struct*" я так понимаю - это указатель на структуру. Вероятно нужно передать
Код:
DllStructGetPtr($vr_array_info)

Поменял 2 строчки кода:

Код:
$vr_array_info = DllStructCreate("ushort status;byte raidType;byte diskNum;dword capacityLow;dword capacityHigh;dword realCapacityLow;dword realCapacityHigh;dword stripeSize;dword blockSize;boolean bNeedMigration;boolean bNeedInit;boolean bOptimized;byte systemDisk;ushort raid_index;int index")
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_info@@YAHHPAU_vr_array_info@@@Z", "int", 0, "struct*", DllStructGetPtr($vr_array_info))


Та же ерунда.

InnI сказал(а):
А для передачи переменной кавычки не нужны. Это я про "$pTest" в кавычках.

Странно, действительно не нужны. Вроде бы изначально без кавычек не получалось, но действительно, не нужны. Спасибо!

Вот основная проблема так и осталась...
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
real_sm
Если у них документация с описанием не совпадает, то в dll может быть всё, что угодно.
 
Автор
R

real_sm

Новичок
Сообщения
18
Репутация
1
Короче, у них еще и типы переназначены:

Код:
typedef int VINT;
typedef int VBOOL;
typedef char VCHAR;
typedef unsigned char VBYTE;
typedef unsigned short VWORD;
typedef unsigned long VDWORD;
typedef unsigned __int64 VDWORD64; (In Linux, will using uint64_t data type.)

Поменял и заработало:

Код:
$vr_array_info = DllStructCreate("ushort status;ubyte raidType;ubyte diskNum;ulong capacityLow;ulong capacityHigh;ulong realCapacityLow;ulong realCapacityHigh;ulong stripeSize;ulong blockSize;int bNeedMigration;int bNeedInit;int bOptimized;ubyte systemDisk;ushort raid_index;int index")
$sTest = DllCall($hDLL, "int:cdecl", "?vr_get_array_info@@YAHHPAU_vr_array_info@@@Z", "int", 0, "struct*", DllStructGetPtr($vr_array_info))


Всем спасибо!
 
Верх