C# "A heap has been corrupted" 使用 sam-ba.dll
C# "A heap has been corrupted" using sam-ba.dll
我正在编写一个 C# 程序来调用 sam-ba.dll
中的 AT91Boot_Scan
函数。在这个 DLL 的 documentation 中,这个函数的签名是 void AT91Boot_Scan(char *pDevList)
。此功能的目的是扫描并 return 已连接设备的列表。
问题:我现在的问题是每次我从C#调用这个函数时,DLL中的代码都会抛出一个a heap has been corrupted
异常。
旁白:据我阅读documentation的理解,char *pDevList
参数是指向函数可以使用的缓冲区数组的指针存储设备名称。但是,当从 C# 调用该方法时,IntelliSense 报告此函数的签名实际上是 void AT91Boot_Scan(ref byte pDevList)
我有点困惑这是为什么。单个字节的长度不足以成为指针。 32 位需要 4 个字节,64 位需要 8 个字节...如果是 ref
关键字使这个参数成为指针,那么我应该传入什么字节?我的缓冲区数组中的第一个字节或第一个缓冲区的第一个字节?
代码: 我写的调用这个函数的C#方法如下
/// <summary>
/// Returns a string array containing the names of connected devices
/// </summary>
/// <returns></returns>
private string[] LoadDeviceList()
{
const int MAX_NUM_DEVICES = 10;
const int BYTES_PER_DEVICE_NAME = 100;
SAMBADLL samba = new SAMBADLL();
string[] deviceNames = new string[MAX_NUM_DEVICES];
try
{
unsafe
{
// Allocate an array (of size MAX_NUM_DEVICES) of pointers
byte** deviceList = stackalloc byte*[MAX_NUM_DEVICES];
for (int n = 0; n < MAX_NUM_DEVICES; n++)
{
// Allocate a buffer of size 100 for the device name
byte* deviceNameBuffer = stackalloc byte[BYTES_PER_DEVICE_NAME];
// Assign the buffer to a pointer in the deviceList
deviceList[n] = deviceNameBuffer;
}
// Create a pointer to the deviceList
byte* pointerToStartOfList = *deviceList;
// Call the function. A heap has been corrupted error is thrown here.
samba.AT91Boot_Scan(ref* pointerToStartOfList);
// Read back out the names by converting the bytes to strings
for (int n = 0; n < MAX_NUM_DEVICES; n++)
{
byte[] nameAsBytes = new byte[BYTES_PER_DEVICE_NAME];
Marshal.Copy((IntPtr)deviceList[n], nameAsBytes, 0, BYTES_PER_DEVICE_NAME);
string nameAsString = System.Text.Encoding.UTF8.GetString(nameAsBytes);
deviceNames[n] = nameAsString;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return deviceNames;
}
我的解决方案尝试:我注意到 byte* pointerToStartOfList = *deviceList;
行没有正确地将 deviceList
的指针分配给 pointerToStartOfList
.地址总是关闭 0x64.
我想如果我在 0x64 偏移量中进行硬编码,那么这两个地址就会匹配,一切都会好起来的。 pointerToStartOfList += 0x64;
然而,尽管强制地址匹配,我仍然收到 a heap has been corrupted
错误。
我的想法:我认为在我的代码中我没有正确创建缓冲区数组,或者我没有正确传递所述数组的指针。
最后我没能sam-ba.dll
工作。我曾尝试围绕 DLL 编写一个 C++ 包装器,但即使那样它仍然会抛出 a heap has been corrupted
错误。我的最终解决方案是将 SAM-BA 可执行文件 sam-ba.exe
及其所有依赖项嵌入到我的 C# 程序中。
然后,每当我需要使用它时,我都会在命令行模式下 运行 sam-ba.exe
并将相关参数传递给它。 SAM-BA documentation 中的第 5.1 节提供了有关如何在命令行模式下 运行 sam-ba.exe
的说明。
即
SAM-BA.exe \usb\ARM0 AT91SAM9G25-EK myCommand.tcl
我正在编写一个 C# 程序来调用 sam-ba.dll
中的 AT91Boot_Scan
函数。在这个 DLL 的 documentation 中,这个函数的签名是 void AT91Boot_Scan(char *pDevList)
。此功能的目的是扫描并 return 已连接设备的列表。
问题:我现在的问题是每次我从C#调用这个函数时,DLL中的代码都会抛出一个a heap has been corrupted
异常。
旁白:据我阅读documentation的理解,char *pDevList
参数是指向函数可以使用的缓冲区数组的指针存储设备名称。但是,当从 C# 调用该方法时,IntelliSense 报告此函数的签名实际上是 void AT91Boot_Scan(ref byte pDevList)
我有点困惑这是为什么。单个字节的长度不足以成为指针。 32 位需要 4 个字节,64 位需要 8 个字节...如果是 ref
关键字使这个参数成为指针,那么我应该传入什么字节?我的缓冲区数组中的第一个字节或第一个缓冲区的第一个字节?
代码: 我写的调用这个函数的C#方法如下
/// <summary>
/// Returns a string array containing the names of connected devices
/// </summary>
/// <returns></returns>
private string[] LoadDeviceList()
{
const int MAX_NUM_DEVICES = 10;
const int BYTES_PER_DEVICE_NAME = 100;
SAMBADLL samba = new SAMBADLL();
string[] deviceNames = new string[MAX_NUM_DEVICES];
try
{
unsafe
{
// Allocate an array (of size MAX_NUM_DEVICES) of pointers
byte** deviceList = stackalloc byte*[MAX_NUM_DEVICES];
for (int n = 0; n < MAX_NUM_DEVICES; n++)
{
// Allocate a buffer of size 100 for the device name
byte* deviceNameBuffer = stackalloc byte[BYTES_PER_DEVICE_NAME];
// Assign the buffer to a pointer in the deviceList
deviceList[n] = deviceNameBuffer;
}
// Create a pointer to the deviceList
byte* pointerToStartOfList = *deviceList;
// Call the function. A heap has been corrupted error is thrown here.
samba.AT91Boot_Scan(ref* pointerToStartOfList);
// Read back out the names by converting the bytes to strings
for (int n = 0; n < MAX_NUM_DEVICES; n++)
{
byte[] nameAsBytes = new byte[BYTES_PER_DEVICE_NAME];
Marshal.Copy((IntPtr)deviceList[n], nameAsBytes, 0, BYTES_PER_DEVICE_NAME);
string nameAsString = System.Text.Encoding.UTF8.GetString(nameAsBytes);
deviceNames[n] = nameAsString;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return deviceNames;
}
我的解决方案尝试:我注意到 byte* pointerToStartOfList = *deviceList;
行没有正确地将 deviceList
的指针分配给 pointerToStartOfList
.地址总是关闭 0x64.
我想如果我在 0x64 偏移量中进行硬编码,那么这两个地址就会匹配,一切都会好起来的。 pointerToStartOfList += 0x64;
然而,尽管强制地址匹配,我仍然收到 a heap has been corrupted
错误。
我的想法:我认为在我的代码中我没有正确创建缓冲区数组,或者我没有正确传递所述数组的指针。
最后我没能sam-ba.dll
工作。我曾尝试围绕 DLL 编写一个 C++ 包装器,但即使那样它仍然会抛出 a heap has been corrupted
错误。我的最终解决方案是将 SAM-BA 可执行文件 sam-ba.exe
及其所有依赖项嵌入到我的 C# 程序中。
然后,每当我需要使用它时,我都会在命令行模式下 运行 sam-ba.exe
并将相关参数传递给它。 SAM-BA documentation 中的第 5.1 节提供了有关如何在命令行模式下 运行 sam-ba.exe
的说明。
即
SAM-BA.exe \usb\ARM0 AT91SAM9G25-EK myCommand.tcl