为什么访问非托管内存会导致System.AccessViolationException
本文关键字:System AccessViolationException 内存 访问 为什么 | 更新日期: 2023-09-27 18:17:57
我试图使用XGBoost的dll (libxgboost.dll)来创建一个DMatrix(这就像一个2D数组),并得到它有多少列。它可以正常运行,直到它在下面的代码中在int cols = ...
行抛出一个System.AccessViolationException
:
using System;
using System.Runtime.InteropServices;
namespace basicXgboost
{
class Program
{
[DllImport("../../libs/libxgboost.dll", CharSet = CharSet.Auto)]
public static extern int XGDMatrixCreateFromFile([MarshalAs(UnmanagedType.LPStr)] string file, int silent, IntPtr outputPtr);
[DllImport("../../libs/libxgboost.dll", CharSet = CharSet.Auto)]
public static extern int XGDMatrixNumCol(IntPtr dmatrixPtr, IntPtr dmatrixColumnsPtr);
static void Main(string[] args)
{
IntPtr dmatrixPtr = Marshal.AllocHGlobal(1000000);
IntPtr dmatrixColumnsPtr = Marshal.AllocHGlobal(10);
int result = XGDMatrixCreateFromFile("../../libs/test.txt", 0, dmatrixPtr);
int cols = XGDMatrixNumCol(dmatrixPtr, dmatrixColumnsPtr);
Marshal.FreeHGlobal(dmatrixPtr);
Marshal.FreeHGlobal(dmatrixColumnsPtr);
}
}
}
为什么访问XGDMatrixNumCol(dmatrixPtr, dmatrixColumnsPtr)
分配的非托管内存会导致System.AccessViolationException
?
一种可能是我对这些函数使用了错误的pinvoke。下面是我使用的每个dll函数的定义:
XGDMatrixCreateFromFile ()
/*!
* 'brief load a data matrix
* 'param fname the name of the file
* 'param silent whether print messages during loading
* 'param out a loaded data matrix
* 'return 0 when success, -1 when failure happens
*/
XGB_DLL int XGDMatrixCreateFromFile(const char *fname,
int silent,
DMatrixHandle *out);
XGDMatrixNumCol ()
/*!
* 'brief get number of columns
* 'param handle the handle to the DMatrix
* 'param out The output of number of columns
* 'return 0 when success, -1 when failure happens
*/
XGB_DLL int XGDMatrixNumCol(DMatrixHandle handle,
bst_ulong *out);
这是我的项目的repo。我使用的是Visual Studio Enterprise 2015。它在Windows 10 Pro(64位)上内置在"调试"模式(针对x64)。libxgboost.dll的X64二进制文件可以在这里找到。尽管链接的repo确实包含libxgboost.dll的副本。
感谢NineBerry的回答,这是我得到的解决方案。
using System;
using System.Runtime.InteropServices;
namespace basicXgboost
{
class Program
{
[DllImport("../../libs/libxgboost.dll", CharSet = CharSet.Auto)]
public static extern int XGDMatrixCreateFromFile([MarshalAs(UnmanagedType.LPStr)] string file, int silent, out IntPtr outputPtr);
[DllImport("../../libs/libxgboost.dll", CharSet = CharSet.Auto)]
public static extern int XGDMatrixNumCol(IntPtr dmatrixPtr, out ulong dmatrixColumnsPtr);
static void Main(string[] args)
{
IntPtr dmatrixPtr;
ulong dmatrixColumns;
int result = XGDMatrixCreateFromFile("../../libs/test.txt", 0, out dmatrixPtr);
int cols = XGDMatrixNumCol(dmatrixPtr, out dmatrixColumns);
}
}
}