C#"堆已损坏"使用sam-ba.dll

时间:2017-03-02 16:22:26

标签: c# pointers atmel heap-corruption

我正在编写一个C#程序来调用AT91Boot_Scan中的sam-ba.dll函数。在此DLL的documentation中,此函数的签名为void AT91Boot_Scan(char *pDevList)。此功能的目的是扫描并返回已连接设备的列表。

问题:我当前的问题是每次从C#调用此函数时,DLL中的代码都会引发a heap has been corrupted异常。

除了:根据我从阅读documentation的理解,char *pDevList参数是指向函数可用于存储设备名称的缓冲区数组的指针。但是,从C#调用方法时,IntelliSense会报告此函数的签名实际为void AT91Boot_Scan(ref byte pDevList)

AT91Boot_Scan signature

我对此为何感到困惑。单个字节不足以成为指针。我们需要4个字节用于32位,8个字节用于64位...如果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关闭。

pointers

我想如果我在0x64偏移量中进行硬编码,那么两个地址将匹配,一切都会好的。 pointerToStartOfList += 0x64; enter image description here

然而,尽管强制地址匹配,我仍然遇到a heap has been corrupted错误。

我的想法:我认为在我的代码中我要么没有正确创建缓冲区数组,要么我没有正确地传递所述数组的指针。

1 个答案:

答案 0 :(得分:0)

最后我无法让sam-ba.dll工作。我曾尝试在DLL周围编写C ++包装器,但即使这样,它仍然会抛出a heap has been corrupted错误。我的最终解决方案是在我的C#程序中嵌入SAM-BA可执行文件sam-ba.exe及其所有依赖项。

然后,每当我需要使用它时,我将在命令行模式下运行sam-ba.exe并将相关参数传递给它。 SAM-BA documentation中的第5.1节提供了有关如何在命令行模式下运行sam-ba.exe的说明。

SAM-BA.exe \usb\ARM0 AT91SAM9G25-EK myCommand.tcl