代码之家  ›  专栏  ›  技术社区  ›  David Brown Muad'Dib

以前没有的访问冲突

  •  3
  • David Brown Muad'Dib  · 技术社区  · 15 年前

    我在召唤格拉夫维兹 as shown here . 当我写那篇博文时,代码工作得很好。现在,我要把 HttpModule 使用该代码呈现graphviz图,但我得到一个 AccessViolationException agmemread .

    // Native signature
    Agraph_t agmemread(char *);
    
    // P/Invoke Signature
    [DllImport(LIB_GRAPH)]
    private static extern IntPtr agmemread(string data);
    
    // Usage
    IntPtr g = agmemread(data);
    

    就像我说的,这在以前是非常有效的。但是现在,我不能让我的代码在任何地方工作。即使是我以前的基于相同代码的graphviz应用程序也不能再工作了。

    我能改变什么可能导致这个?我甚至还没有下载新版本的graphviz或任何东西,所以DLL都是相同的。

    编辑: 我试图改变 string StringBuilder 但结果是一样的。然后,我添加了一个 MarshalAs 属性:

    static extern IntPtr agmemread([MarshalAs(UnmanagedType.LPWStr)] string data);
    

    有了这个,我再也不能 访问违反异常 ,但graphviz未能正确读取字符串并返回空指针。

    2 回复  |  直到 12 年前
        1
  •  6
  •   Hans Passant    15 年前

    非托管代码很少需要C的大量帮助才能开始生成访问冲突。您的p/invoke签名没有任何错误,这不是原因。

    非托管代码中最常见的AVS源是堆损坏。C/C++代码没有垃圾收集器,必须显式地管理内存。它不仅要注意释放内存(否则会泄漏),还要负责分配正确的大小,并确保写入分配内存的代码不会超过分配内存块的末尾,也不会写入已释放的内存。最后一个要求是C/C++代码经常失败。

    堆损坏的问题在于它非常难以诊断。它可能会在很长一段时间内被忽视。典型的损坏是内部堆结构受到破坏,或者另一个堆分配中的数据被覆盖。直到稍后释放堆块或使用覆盖的数据时,这才导致问题。产生异常的代码实际上并不负责先前所做的损坏。这会让你走上错误的道路,试图找到问题的根源。

    找到真正的麻烦制造者是非常困难的,你只有几个面包屑来找出可能出了什么问题。当您有C/C++源代码时,它非常困难,但是用调试分配器在调试生成中运行它是有帮助的。没有源代码是不可能的。

    除非您能够指出使用之前调用的API的问题,否则您需要供应商或支持组的帮助才能真正解决此问题。祝你好运。

        2
  •  0
  •   Community CDub    7 年前

    我也有同样的问题 P/Invoke 签名需要添加 CallingConvention=CallingConvention.Cdecl. graphviz库是C调用约定,而不是 StdCall .

    this thread .