在C#中调用pandoc的函数(haskell)时,总是出现错误:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
对应的英文错误信息如下:
An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
详情见博文:C#调用haskell遭遇Attempted to read or write protected memory
如何解决这个问题呢?
public static extern IntPtr markdownToHtml(byte[] markdown);
改为:
public static extern IntPtr markdownToHtml(IntPtr markdown,int size);
或者
public static extern IntPtr markdownToHtml( [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.U1)]byte[] markdown);
传入参数markdown的值在Haskell中是能正常拿到的
@dudu: 你的错误是出现在 var html = Marshal.PtrToStringAnsi(intPtr) 这条语句吗?
@Launcher: 错误出在Haskell代码中取writeHtmlString的结果时,如果Haskell代码中直接返回字符串,就不会出问题
@dudu: 错误是出现在 Native.markdownToHtml(System.Text.Encoding.UTF8.GetBytes(text)) 这句对吧!
也就是 markdown 传进去了,你的 haskell 能拿到,但是无法访问markdown 中的内容,对吗?
@dudu: 仔细看了你的代码,应该是返回的缓冲区被回收了,所以导致内存访问错误。直接返回字符串的话,因为是常量,只要 DLL 不卸载,就会一直有效。
@Launcher: 修改成这样:
public static extern IntPtr markdownToHtml(byte[] markdown,IntPtr buff,int size);
haskell 将内容写进你预先分配好的 buff 中去。
或者在 haskell 中这样(不会 haskell,我用c): void * p = malloc(1024);return p; 当然,这会造成内存泄露,所以应该在 haskell 中多准备两个方法:
haskell_alloc(xxxxxxxxxx);
haskell_free(p);
@Launcher: 很可能是这个原因
@dudu: 你的第二个链接不错,原来 libpandoc 有这样的 API,不仅要求提供输入输出缓冲区,连读、写回调都有。
@Launcher: libpandoc是2010年的开源项目,现在无法编译通过,而且弄得有些复杂
@dudu: 这个库是干啥的?
@Launcher: 最强大的makdown引擎非pandoc莫属,libpandoc可以编译成dll供外部调用
@Launcher: 问题解决了,详见:困扰多日的C#调用Haskell问题竟然是Windows的一个坑
@dudu: 不明白!是说你编译成的非托管的 DLL,在 Windows 2008 上无法运行,但是在 Windows 2012 上能运行,是这样吗?如果是的话,问题可能出在你的编译选项上,或者程序中的一个隐含的 BUG 所致(比如缓冲区溢出)。
那么在 Windows 8 、Windows 7 和 Windows XP 上能运行吗?
@Launcher: 没有这样的环境,在Windows 8、Windows 7、Windows XP上运行也没有实际意义
@dudu,你给1w分不足为怪啊。你怎么好意思给50分