【问题标题】:Why do I get an AccessViolationException when breaking just before calling a DllImport?为什么在调用 DllImport 之前中断时会出现 AccessViolationException?
【发布时间】:2012-04-25 09:55:18
【问题描述】:

我正在尝试在 C# 中使用非托管 DLL 中的 C 函数。

函数的签名是:

const char*  CDECL get_lame_version       ( void );

我是这样导入函数的:

[DllImport("libmp3lame.dll")]
static extern string get_lame_version();

如果我调用了这个函数,但我在调用之前中断了,然后按 F5,就会抛出 AccessViolationException。

首先执行中断只是在调用之前

然后我按 F5 出现异常:

如果执行中断调用,则不会抛出异常:

所以我的问题是:我的代码有什么问题吗?如果不是,那是怎么回事?

编辑

这里是get_lame_version的定义:

/*! Get the LAME version string. */
/*!
  \param void
  \return a pointer to a string which describes the version of LAME.
*/
const char *
get_lame_version(void)
{                       /* primary to write screen reports */
    /* Here we can also add informations about compile time configurations */

#if   LAME_ALPHA_VERSION
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " "
        "(alpha " STR(LAME_PATCH_VERSION) ", " __DATE__ " " __TIME__ ")";
#elif LAME_BETA_VERSION
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " "
        "(beta " STR(LAME_PATCH_VERSION) ", " __DATE__ ")";
#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0)
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION);
#else
    static /*@observer@ */ const char *const str =
        STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION);
#endif

    return str;
}

【问题讨论】:

  • 请参阅this postthis post,了解如何在函数返回 char* 时专门处理返回字符串的互操作。

标签: c# .net visual-studio-2010 debugging pinvoke


【解决方案1】:

pinvoke 签名错误。应该是:

[DllImport("libmp3lame.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr get_lame_version();

要调用它,您需要这样做;

string version = Marshal.PtrToStringAnsi(get_lame_version());

您不能依赖 p/invoke 编组器来编组字符串值,因为它不拥有该字符串。 DLL 拥有该字符串。

更重要的是,您应该指定 LAME DLL 函数的调用约定,否则您将得到默认的 pinvoke 调用约定 stdcall。这对于没有参数的函数来说并不重要,但这是一个好习惯。

【讨论】:

  • 我通常不放这样的 cmets,但非常感谢您的回答!
【解决方案2】:

访问冲突是由非托管代码引起的,而不是您的 C# 代码。如果没有看到非托管代码,很难说问题出在哪里。

【讨论】:

  • 我添加了函数的定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多