通过引用传递struct导致AccessViolationException

时间:2009-08-25 03:26:07

标签: c# reference struct pinvoke

我的另一个P / Invoke问题!我有这个C函数:

int _ei_x_new(ei_x_buff* x);

基本上,它初始化一个新的缓冲区结构。在C#中,我有这个:

[DllImport(EIDLL, EntryPoint = "_ei_x_new")]
public static extern int ei_x_new(out ei_x_buff x);

ei_x_buff非常简单:

typedef struct ei_x_buff_TAG {
    char* buff;
    int buffsz;
    int index;
} ei_x_buff;

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ei_x_buff {
    [MarshalAsAttribute(UnmanagedType.LPStr)]
    public string buff;
    public int buffsz;
    public int index;
}

但是当我这样做时:

ei_x_buff buffer;
Ei.ei_x_new(out buffer);

我收到 AccessViolationException

  

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

我需要分配一些内存吗?这是一段如此简单的代码,我无法看到任何明显的问题。

编辑: _ei_x_new的原生代码:

// In my wrapper library
DLL_EXPORT int _ei_x_new(ei_x_buff* x) {
    return ei_x_new(x);
}

// In external library being wrapped
int ei_x_extra = 100;

int ei_x_new(ei_x_buff* x)
{
    x->buff = malloc(ei_x_extra);
    x->buffsz = ei_x_extra;
    x->index = 0;
    return x->buff != NULL ? 0 : -1;
}

3 个答案:

答案 0 :(得分:0)

一些事情

  • 在PInvoke签名中使用out not not,因为您希望在两个方向上编组数据(进出本机函数)
  • 您是否可以发布本机签名,因为它们可能是定义的问题。特别是buff成员

编辑

为了消除一种可能性,将buff成员切换为没有属性的IntPtr类型。如果这不会导致崩溃,那么它可能是字符串类型的编组问题。

答案 1 :(得分:0)

您是否使用fixed语句将缓冲区标记为固定在内存中:

示例:

// assume class Point { public int x, y; }
// pt is a managed variable, subject to garbage collection.
Point pt = new Point();
// Using fixed allows the address of pt members to be
// taken, and "pins" pt so it isn't relocated.
fixed ( int* p = &pt.x )
{
    *p = 1; 
}

答案 2 :(得分:0)

如果您只是在C端正确初始化缓冲区,我认为它也适用于字符串。请记住,缓冲区malloc返回可能包含垃圾,因此您应该添加类似

的内容

if(x-> buff)x-> buff [0] ='\ 0';

您可能想要仔细检查的另一件事是您在本机和托管端使用相同的调用约定。除非您在DllImport属性中指定其他内容,否则CLR将采用_stdcall。