C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?

Posted

技术标签:

【中文标题】C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?【英文标题】:allocVector() in C and System.AccessViolationException: Attempted to read or write protected memory? 【发布时间】:2015-06-06 19:43:36 【问题描述】:

allocVector() 函数有问题。我用 C 语言编写了一个可以在 R 中调用的代码 (DLL)。我想在 C# 中将该 DLL 的方法调用到我的应用程序中。 DLL 代码工作正常,但是当编译器到达下一行时 ROut = allocVector(INTSXP, 2*3) 它给出了以下异常: 未处理的异常:System.AccessViolationException:试图读取或写入受保护的内存。 代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <R.h>
#include <Rinternals.h>
#include <Rmath.h>
#include <R_ext/Applic.h>
#include <R_ext/Lapack.h>
#include <Rdefines.h>
#ifdef __cplusplus
extern "C" 
#endif
    void castType(int *result)
    
        SEXP ROut;
        ROut = allocVector(INTSXP, 2*3)
        ROut = PROTECT(ROut);
        int *clustOut = INTEGER(ROut); 
        result= clustOut ; 
     
#ifdef __cplusplus

#endif

【问题讨论】:

【参考方案1】:

快速阅读,我认为您使用值 6 作为指针的值。里面还有其他问题。

退后一步,我为您的 C#/C 互操作提出几点建议:

如果您在此 API 中没有很多自己的现有 C 代码,我建议您将其移植到 C# 并使用 R.NET(NuGet package、source code) 如果你确实有大量的 C/C++ 代码,或者绝对需要 C 层,你可以看看这个sample code。在回答之前,我把它放在一起测试了几件事,所以我不妨提交源代码。

为了其他读者,从问题中的功能阐述的症结是:

C API:

void c_api_call(int * result)

    SEXP p = some_R_calculations();
    int* int_ptr = INTEGER_POINTER(p);
    int n = length(p);
    for (int i = 0; i < n; i++)
        result[i] = int_ptr[i];
    // We are done with p; irrespective of where some_R_calculations got it, 
    // we can notify the R GC that this function releases it.
    R_ReleaseObject(p);

C# 互操作包装器:

public class CppInterop : DynamicInterop.UnmanagedDll // http://www.nuget.org/packages/DynamicInterop/

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void _c_api_call([In, Out] [MarshalAs(UnmanagedType.LPArray)] int[] values);

    public int[] CreateArray()
    
        // These two following references could be cached for efficiency later on.
        var getLength = this.GetFunction<_c_api_call_getlength>("c_api_call_getlength");
        var getValues = this.GetFunction<_c_api_call>("c_api_call");

        // As far as I know it is preferable, if not needed, to handle arrays in two steps:
        // we need to know the expected length to allocate in C# buffer memory.
        int expectedLength = getLength();
        int[] result = new int[expectedLength];
        getValues(result);
        return result;
    

【讨论】:

感谢您的回答。我遵循了在您的代码中使用 rClr 的方法,但是在编译时遇到了以下错误: 错误 LNK1104: 无法打开文件 'Rdll.lib' C:\Users\Stephan\Documents\GitHub\rdotnet-support\wrapcppdll\mycpp\LINK mycpp 在站点 codeplex 上调用它们以在我的系统上构建 rClr 时,我按照以下步骤操作: %R% CMD check rClr %R% CMD REMOVE rClr %R% CMD INSTALL rClr 我收到了消息构建成功。 但我不知道为什么我总是收到错误消息:无法打开文件 'Rdll.lib' 我还有一个关于 R.NET 的问题:是否可以通过某些特定的方法调用 R 的函数包,例如“rrcov”?如果您向我推荐一些材料,我将不胜感激。提前致谢,

以上是关于C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?的主要内容,如果未能解决你的问题,请参考以下文章

c语言和VC.C++和VC++的的详细区别

c语言和c++有啥关系

C语言和C++有啥区别?

OC和C的区别?

C语言和C++的区别

c语言和c++和c#的区别