困扰多日的C#调用Haskell问题竟然是Windows的一个坑

最近一直被C#调用Haskell时的“尝试读取或写入受保护的内存”问题所困扰(详见C#调用haskell遭遇Attempted to read or write protected memoryC#调用haskell时的“尝试读取或写入受保护的内存”问题),而且困在其中,越陷超深,无法自拔,差点弃用C#解决我们面临的问题。

问题是这样的,只要在Haskell代码中对字符串进行操作,在C#调用时就会引发异常:

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.

示例Haskell代码如下:

如果直接返回字符串,则一切正常,示例Haskell代码如下:

C#调用示例代码:


class Native
{
[DllImport("libpandoc", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern IntPtr markdownToHtml(byte[] markdown);
}

public class Processor
{
public string Process(string text)
{
var intPtr = Native.markdownToHtml(System.Text.Encoding.UTF8.GetBytes(text));
var html = Marshal.PtrToStringAnsi(intPtr);
return html;
}
}

你也许会问——吃饱撑着了,为什么要用C#调用Haskell?

没撑着!因为史上最强大的Markdown引擎pandoc就是用Haskell开发的,不是C#,不是Java,不是PHP,不是Python,也不是C/C++,更不是Objective-C。真正要比的不是语言,而且是用语言开发出来的东西。

你也许要问——很多人看不起的微软家的C#能调用高上大的Haskell?

当然能!而且经过了实际验证,详见经过实际验证的C#调用Haskell的方法。虽然是通过FFI(ForeignFunctionInterface),借助C编译成非托管的dll,但不管怎么样,C#做到了。

但当我们用C#调用Haskell解决实际问题时,遭遇了“Attempted to read or write protected
memory. ”问题,反复折腾找不到解决之道,处于绝望中,以为“C#可以调用Hakell"是一个“骗局”。

。。。

今天上午,当我们把编译好的程序从Windows Server 2008 R2复制到Windows Server
2012上运行时,奇迹竟然出现了——运行正常,并且得到了正确的结果。

这时你也许又要问——不是自找麻烦吗,为什么不一开始就用Windows Server 2012?

不是自找麻烦,是麻烦自己找上门的。因为编译Haskell代码需要安装Haskell Platform(集成了ghc),而Haskell
Platform不能在Windows Server 2012正常安装,只能被迫在Windows Server 2008上安装(当时也被折腾了)。

万万没有想到的是,Windows Server 2008上编译出来的程序不能在Windows Server
2008上正常运行,却奇迹般地能在Windows Server 2012上能正常运行。这是不是Windows的一个坑呢?

由此想到我们在阿里云上曾经遭遇的“黑色10秒”问题,是因为Windows Server 2008在WAS(Windows Process
Activation Service)中使用了spinlock,而虚拟化技术对spinlock支持不好,最终也是通过换用Windows Server
2012解决了问题。这虽然不能说是Windows Server 2008的一个坑,但说明了一点——使用Windows
Server,2008要小心!

时间: 2024-10-27 06:04:03

困扰多日的C#调用Haskell问题竟然是Windows的一个坑的相关文章

经过实际验证的C#调用Haskell的方法

[系统环境] Windows Server 2008 R2,Haskell Platform 2013.2.0.0,ghc 7.6.3,cabal 1.16.0 [操作步骤] 1. 安装Windows版Haskell Platform(不支持Windows Server 2012),Haskell Platform集成了cabal(相当于.NET中的msbuild+nuget), ghc(Glasgow Haskell Compiler,Haskell编译器) 2. 编写Haskell代码保存于

HttpClient调用.net发布的带Windows NTML验证的webservice

使用HttpClient调用: 先要通过Windows NTML验证,然后才能调用 . 1 class WebServiceTest 2 { 3 4 /** 5 * 获取接口数据 6 * @param soapRequest 7 * @return String 8 */ 9 public String postSoapRequest(String soapRequest){ 10 CloseableHttpClient httpclient = HttpClients.createDefaul

调用微信扫一扫功能,踩坑'invalid signature'

在vue项目中,调用微信扫一扫功能,在安卓系统下完全正常,ios系统下却报错'invalid signature'的错误,这可能令许多小伙伴困惑,经过查询大量博客相关资料,才找到了解决的方法. 原因:由于在ios和android中,location.href在spa页面的机制不同(不同在于ios是只要不刷新页面,href就不会改变,在vue项目中就会出现类型的问题),所以我们需要借助路由钩子函数,手动改变其页面的url地址,这样ios系统的手机才能正常调起微信扫一扫. beforeRouteEn

Haskell环境搭建(windows)(一)

1.官网上(https://www.haskell.org/platform/windows.html)下载Haskell Platform,最新版本为8.2.1,只支持64位,有个core版和full版,full版包含了库,就下full版试试 2.cmd下输入 "cabal user-config init",可以看到配置文件的路径,找到配置文件,添加输入 extra-prog-path: C:\Program Files\Haskell Platform\8.2.1\msys\us

通用网页调用本地应用程序方案(windows平台)

一.更新注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\receiveOutOfArg] "URL Protocol"="D:\\LongHaibin\\Learn\\Net\\receiveOutOfArg\\receiveOutOfArg\\bin\\Debug\\receiveOutOfArg.exe" @="applicationName" [HKEY_CLASSES

debug版本的DLL调用release版本的DLL引发的一个问题

stl的常用结构有 vector.list.map等. 今天碰到需要在不同dll间传递这些类型的参数,以void*作为转换参数. 比如 DLL2 的接口 add(void*pVoid); 1.在DLL1中调用该接口, struct st_headerTerminalRes{ st_headerTerminalRes(){id=0;} int id; int type;//restype 1=mc 2=camera int resId; int headerId;};typedef vector<

调用淘宝订单接口想到的一个问题

在淘宝提供的SDK中,并没有对接口调用返回结果进行安全性验证. 这样就存在一种可能,比如我的订单接口调用在网络传输过程中被劫持了(hacker伪造了格式一样的返回信息),那么就可能导致我的订单系统会引入一些实际上并没有在淘宝平台存在的订单,此时,如果订单系统的客服人员没有比对两个平台的订单的话,订单系统上多出的伪造的订单就可能被发货出去. 解决办法: 淘宝订单接口可以在接口返回的信息中,返回签名,然后sdk中对接口返回信息中的签名进行验证即可

cefsharp 关于C# 调用JavaScript的一个坑

之前开发的一个产品在上线后总有奇怪的BUG,经过一番调试后发现在使用CEF控件的 EvaluateScriptAsync 这个方法的时候,并不能保证成功. 经过一番查询,发现官方文档(https://github.com/cefsharp/CefSharp/wiki/General-Usage#devtools)有这么一段 2. How do you call a JavaScript method that returns a result? If you need to evaluate c

关于在for循环里调用ajax时只能取到最后一个数据的bug的解决方法

首先,造成这中情况的原因在与ajax的异步请求机制,for循环的运行速度远大于ajax异步请求的速度,这就造成了ajax运行时,需要的在for循环里的参数已经运行到最后一个了,所以取到的都是最后一个参数数据. 解决方法:将ajax的请求封装成一个单独的方法,然后在for循环里调用该方法.