2016-11-14 105 views
-1

我正在尝试使用XGBoost's dll(libxgboost.dll)创建一个DMatrix(就像一个二维数组),并获取它有多少个列。它运行正常,直到它在下面的代码抛出一个System.AccessViolationExceptionint 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); 

Here是我的项目的回购协议。我正在使用Visual Studio Enterprise 2015。它在Windows 10 Pro(64位)上以“调试”模式(目标x64)构建。可以找到libxgboost.dll的x64二进制文件here。虽然链接的回购确实包含libxgboost.dll的副本。

+0

'Marshal.AllocHGlobal(10);'分配10个字节还是10个整数?你有多确定只有10列? –

+0

我认为它分配10个字节,如果我正在阅读[文档](https://msdn.microsoft.com/en-us/library/s69bkh17(v = vs.110).aspx)的权利。 10只是我用来在内存中存储一​​个整数的任意数量的字节(它可以指多于10列)。 – cycloidistic

+0

如果XGDMatrixNumCol填充bst_ulong参数,那么您需要知道bst_ulong有多大 - 是多少还是少于10个字节? –

回答

-1

这是我得到的解决方案,谢谢NineBerry's answer

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); 
    } 
    } 
} 
+1

检查返回值。他们在那里是有原因的。 XGDMatrixCreateFromFile可能会失败。 – MarcD

相关问题