困扰多日的C#调用Haskell问题竟然是Windows的一个坑
最近一直被C#调用Haskell时的“尝试读取或写入受保护的内存”问题所困扰(详见C#调用haskell遭遇Attempted to read or write protected memory,C#调用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要小心!
困扰多日的C#调用Haskell问题竟然是Windows的一个坑的更多相关文章
- C#调用haskell遭遇Attempted to read or write protected memory
1. Haskell的代码如下: 上面的代码中readMarkdown与writeHtmlString是pandoc中的函数,newString的作用是将String转换为IO CString. 2. ...
- 经过实际验证的C#调用Haskell的方法
[系统环境] Windows Server 2008 R2,Haskell Platform 2013.2.0.0,ghc 7.6.3,cabal 1.16.0 [操作步骤] 1. 安装Windows ...
- paip.java c# .net php python调用c++ c dll so windows api 总结
paip.java c# .net php python调用c++ c dll so windows api 总结 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来 ...
- Notepad++中调用cl.exe编译器(Windows)
Notepad++中调用cl.exe编译器(Windows) 近来在notepad++中写代码,写完后总是习惯性的想去VS里面编译一下,看看代码是否有误.但有时候一些零碎的小文件总是懒得再VS中打开, ...
- 我用C#调用C编译的dll中有这样一个函数,函数大概的功能就是把数据保存到buf缓冲区中:
我用C#调用C编译的dll中有这样一个函数,函数大概的功能就是把数据保存到buf缓冲区中: C/C++ code ? 1 int retrieve(int scanno,void* buf); 在 ...
- 关于php调用.net的web service 踩过的坑
从前一阵开始,公司要和对方做web service对接.由于对方使用.net语言,而我方使用php.本来经理是要求我们也用.net写web service的服务端.而我上学时学的.net全忘了... ...
- 摄像头调用代码 笔记本的话,本身有一个摄像头,由于用的usb摄像头,需要把笔记本的摄像头禁用后,再使用
摄像头调用代码 笔记本的话,本身有一个摄像头,由于用的usb摄像头,需要把笔记本的摄像头禁用后,再使用 <!DOCTYPE html> <html lang="en&quo ...
- 将前端js异步调用的多个服务合并为一个前端服务
将前端js异步调用的多个服务合并为一个前端服务 1. 减少前端js异步请求的次数改善浏览体验 2. 方便地针对单个接口做异常降级处理
- 三界商城 ajax调用城市接口,竟然需要登录,调用的接口需要登录,如果不登录 重定向到登录
现象 商家入驻 填写信息的 ajax请求没有数据 network->name-headers 返回302 发现调用的接口,需要登录,否则重定向登录 //初始化用户信息查询 public func ...
随机推荐
- COleChangeSourceDialog不能Change Source的解决方法
在微软给的例子OClient中,有选中一个OLE对象然后Change Source的功能,但是会报错.分析了一下是这样的: void CMainView::OnOleChangeSource() ...
- javascript generate a guid
function Guid() { var random = (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); retu ...
- 关于CacheLookup一个有趣的问题
今天写一个与其他系统进行物料同步的接口,通过COM Business Connector调用Axapta3.0的方法将数据插入到物料表中,中间发生异常,事务回滚,再次调用的时候提示刚刚发生异常的物料已 ...
- C# 队列集合的使用
using System; using System.Collections.Generic; using System.Text; using System.Collections; namespa ...
- 英语语法 It all started the summer before second grade when our moving van pulled into her neighborhood
It all started the summer before second grade when our moving van pulled into herneighborhood It all ...
- 计算机病毒实践汇总四:netcat使用方法
在尝试学习分析的过程中,判断结论不一定准确,只是一些我自己的思考和探索.敬请批评指正! 1. netcat概述 (1)特性 "TCP/IP协议栈瑞士军刀",可以被用在支持端口扫描. ...
- swift使用swifthttp
1.https://github.com/daltoniam/SwiftHTTP下载 2.将项目中的Source文件夹中的所有.swift拖到项目中 3.不用import 4.直接用HTTP.GET或 ...
- Linux C _exit函数与exit函数的联系与区别
一.联系 1.功能上,_exit和exit函数都是让进程正常退出,即关闭进程所打开的文件描述符,释放已占用内存和其他资源. 二.区别 1._exit函数在头文件unistd.h中声明,而exit在头文 ...
- 算法与数据结构实验题6.4 order (二叉树)
1.题目: 2.代码: #include<iostream> #include<algorithm> using namespace std; struct Node { in ...
- 命令行参数 main()函数设计
一.main()函数的形式 int main( void )--无参数形式 { ... return 0; } int main( int argc, char *argv[] )--带参数形式 { ...