- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
今天我将我的开发机器从 Ubuntu 10.04 LTS 更新到 Ubuntu 12.04 LTS(或 ghc 6.12.1
到 ghc 7.4.1
),我遇到了一个非常奇怪的问题我当前项目的行为。
几个小时后,我将其简化为以下代码:
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Data.Word
import Text.Printf
import Foreign
foreign import ccall "dynamic"
code_void :: FunPtr (IO ()) -> (IO ())
main :: IO ()
main = do
entryPtr <- (mallocBytes 2)
poke entryPtr (0xc390 :: Word16) -- nop (0x90); ret(0xc3) (little endian order)
_ <- printf "entry point: 0x%08x\n" ((fromIntegral $ ptrToIntPtr entryPtr) :: Int)
_ <- getLine -- for debugging
code_void $ castPtrToFunPtr entryPtr
putStrLn "welcome back"
我试图在运行时生成一些代码,跳转到它,然后再返回。使用 Makefile,一切都很好:
$ make
ghc --make -Wall -O2 Main.hs -o stackoverflow_segv
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking stackoverflow_segv ...
./stackoverflow_segv
entry point: 0x098d77e0
welcome back
但是,如果我直接从 shell 调用二进制文件:
$ ./stackoverflow_segv
entry point: 0x092547e0
Segmentation fault (core dumped)
这种行为是可重现的(幸运的是?)。
使用 gdb
、objdump
和 /proc
我发现:
$ gdb -q stackoverflow_segv
Reading symbols from /home/lewurm/stackoverflow/stackoverflow_segv...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/lewurm/stackoverflow/stackoverflow_segv
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
entry point: 0x080fc810
在按下 enter 之前,我切换到第二个终端:
$ cat /proc/`pgrep stackoverflow`/maps
[...]
08048000-080ea000 r-xp 00000000 08:01 2492678 /home/lewurm/stackoverflow/stackoverflow_segv
080ea000-080eb000 r--p 000a2000 08:01 2492678 /home/lewurm/stackoverflow/stackoverflow_segv
080eb000-080f1000 rw-p 000a3000 08:01 2492678 /home/lewurm/stackoverflow/stackoverflow_segv
080f1000-08115000 rw-p 00000000 00:00 0 [heap]
[...]
再回来:
<enter>
Program received signal SIGSEGV, Segmentation fault.
0x0804ce3c in s2aV_info ()
嘘。让我们看看这段代码做了什么:
$ objdump -D stackoverflow_segv | grep -C 3 804ce3c
804ce31: 89 44 24 4c mov %eax,0x4c(%esp)
804ce35: 83 ec 0c sub $0xc,%esp
804ce38: 8b 44 24 4c mov 0x4c(%esp),%eax
804ce3c: ff d0 call *%eax
804ce3e: 83 c4 0c add $0xc,%esp
804ce41: 83 ec 08 sub $0x8,%esp
804ce44: 8b 44 24 54 mov 0x54(%esp),%eax
呃,跳转到 *%eax
。 %eax
又是什么?
(gdb) info reg eax
eax 0x80fc810 135251984
嗯,实际上它只是代码缓冲区。查看 /proc/*/maps
告诉我们,这个页面不可执行(rw-p
,对吧?)。 但是,在make
中执行也是一样的。
这里有什么问题吗?
顺便说一句,代码也可以通过 gist 获得
最佳答案
临时解决方案是使用mprotect(3)
并将内存区域明确设置为可执行。 mprotect(3)
需要一个对齐的内存块,因此需要 memalign(3)
。
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Data.Word
import Text.Printf
import Foreign
import Foreign.C.Types
foreign import ccall "dynamic"
code_void :: FunPtr (IO ()) -> (IO ())
foreign import ccall "static sys/mman.h"
mprotect :: CUInt -> CUInt -> Int -> IO ()
foreign import ccall "static stdlib.h"
memalign :: CUInt -> CUInt -> IO (Ptr a)
main :: IO ()
main = do
entryPtr <- memalign 0x1000 0x2
poke entryPtr (0xc390 :: Word16) -- nop (0x90); ret(0xc3) (little endian order)
let i_entry = (fromIntegral $ ptrToIntPtr entryPtr) :: Int
-- 0x7 = PROT_{READ,WRITE,EXEC}
mprotect (fromIntegral i_entry) 2 0x7
_ <- printf "entry point: 0x%08x\n" i_entry
_ <- getLine -- for debugging
code_void $ castPtrToFunPtr entryPtr
putStrLn "welcome back"
关于linux - GHC:奇怪条件下的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10341943/
runghc 和 ghc 有什么区别? 我运行了一个简短的程序,似乎可以用两者编译,除了我用 runghc 得到了以下内容,但不是普通的 ghc: error: Variable not in sco
如果 friend 想要运行我的 Haskell 二进制文件,他是否必须先安装 Haskell,还是可以立即自行运行二进制文件? Mac、Windows 和 Linux 上的答案相同吗? 最佳答案 G
ffunction glMultiDrawElements 需要一个指向指针的指针作为其参数之一。如何从 StorableArray Int a 获取 Ptr(Ptr a) ? 最佳答案 您需要先将索
module Has (r,p,s) where import Prelude ((==),Bool(..),otherwise,(||),Eq) import qualified Data.List
我已经构建了 ghc-HEAD,我想尝试构建所有的 stackage lts 或 nightly 看看它能做多少。 无论我说什么都无法说服 stack 使用我的新 ghc 构建任何东西。我尝试设置如下
我正在使用 Emacs (24.3.1) 在 haskell-mode 中与 ghc-mod 一起使用 Haskell。 现在除了一件烦人的事情外,一切都很好: GHC 信息缓冲区中的每个输出仅包含第
为什么升级到 OSX Mavericks 后我的 GHC 7.6.3 不能工作? 最佳答案 花了很长时间才弄清楚如何同时使用 OSX 10.9 和 GHC 7.6.3,这里有一些技巧可以帮助您重新构建
我有一个带有 cabal 文件的主要 Haskell 可执行程序。在那里,我指定 ghc-options . 这个可执行文件链接到野外的其他库。请问ghc-options忽略这些库的 cabal 文件
我有一个使用 -Wall 编译的库,并且我有一个使用 -Wall -Wno-incomplete-patterns 的测试套件 当我使用 stack ghci --test 启动 ghci 时,ghc
我正在尝试使用以下脚本在 Windows 上安装 GHC(并将 ghc 放在路径中),但是当我尝试运行 ghci --version 时它失败了。我认为脚本有问题。 install: - ps:
我在 $HOME 中安装了 ghc-7.2.2 unknown linux tar.bz2在archlinux上。 在使用 cabal-dev 成功安装多个软件包后,尝试安装例如。我得到的解析数字、文
想法 我正在写 DSL ,编译为 Haskell。 该语言的用户可以定义自己的不可变数据结构和相关函数。关联函数是指属于数据结构的函数。 例如,用户可以编写(在“pythonic”伪代码中): dat
(我的问题是在没有 haskell-platform、ghc、cabal 等的情况下分发二进制文件) 我需要部署一个结构良好的 haskell 应用程序(Yesod 脚手架),但我有磁盘空间限制。 G
我试图将 Cygwin 安装程序指向 http://haskell.org/ghc/cygwin ,但安装程序无法找到 setup.ini.sig。如果可能的话,我该如何编辑我的 .bashrc 以引
我有一个现有的 Haskell 函数,它使用 GHC API 从模块中动态加载已编译的代码。它基于博客文章中的代码 Dynamic Compilation and Loading of Modules
我使用:Ubuntu 上的 GHC 7.6.3(通过 apt-get install haskell-platform) 从当前存储库安装它。 正在尝试安装ghc-mod ,因为我的 ide 插件需要
AFAIK,有两种方法可以在 Haskell 中获取用于调试的调用堆栈: 添加 HasCallStack代码中的约束 使用 ghc -prof -fprof-auto-top 编译代码 我的测试代码:
我想用 64 位 GHC 构建 32 位 DLL。这是最小的例子。 测试.hs {-# LANGUAGE ForeignFunctionInterface #-} module Test where
ghc-gc-tune 0.2.1 可以与 ghc 7.4.1 一起使用吗?看来 ghc-gc-tune 已经有一段时间没有更新了,可能只适用于 ghc 6.x?我找不到任何可靠的信息。 我收到以下错
语言扩展 ExplicitForall 使得使用 forall 绑定(bind)类型变量成为可能但不是必需的。 例如,下面的程序可以编译 {-# LANGUAGE ExplicitForAll #-}
我是一名优秀的程序员,十分优秀!