编译Haskell程序时出现__stginit_多重定义错误求助
解决GHC链接阶段出现“multiple definition”错误的问题
你跟着《真实世界Haskell》(RWH)的示例写Haskell程序时遇到了链接错误,我来帮你搞定这个问题。
先还原一下你的场景:你有两个文件——Jlib.hs(定义JSON数据结构的模块)和Main.hs(主函数),编译时GHC在链接阶段崩溃,报了重复定义的错误。
你的文件与操作细节
文件列表
Jlib.hs Main.hs
Main.hs 代码
module Main where import Jlib import System.Environment main::IO() main=print(JObject[("p0",JNumber 3),("p1",JString "asta")])
你执行的编译命令
ghc -c Jlib.hs ghc -o Main Main.hs Jlib.o
得到的错误信息
$ ghc -o Main Main.hs Jlib.o [2 of 2] Compiling Main ( Main.hs, Main.o ) Linking Main.exe ... Jlib.o:fake:(.data+0x0): multiple definition of `__stginit_Jlib' .\Jlib.o:fake:(.data+0x0): first defined here Jlib.o:fake:(.data+0x60): multiple definition of `Jlib_zdfShowJValue_closure'
当前文件夹结构
Jlib.hs Jlib.o Jlib.hi Main.hs Main.o Main.hi
补充的Jlib.hs代码
module Jlib( JValue(..), getString, getInt, getBool, getObject, getArray ) where data JValue=JString String |JNumber Double |JBool Bool |JNull |JObject [(String,JValue)] |JArray [JValue] deriving (Eq,Ord,Show) getString::JValue->Maybe String getString (JString s)=Just s getString _=Nothing getInt::JValue->Maybe Int getInt (JNumber n)=Just (truncate n) getInt _= Nothing getBool::JValue->Maybe Bool getBool (JBool b)=Just b getBool _=Nothing getObject (JObject obj)=Just obj getObject _=Nothing getArray (JArray a)=Just a getArray _=Nothing
问题原因
这个错误的核心是你在链接时重复引入了Jlib.o文件:当你编译Main.hs时,GHC会自动检测到它依赖Jlib模块,然后自动去查找并链接对应的Jlib.o和Jlib.hi文件。而你手动在命令里加上Jlib.o,就导致同一个目标文件被链接了两次,自然会报“multiple definition”(重复定义)的错误。
解决方案
只需要去掉编译命令里的Jlib.o即可,有几种可行的方式:
方式1:分步编译(推荐)
- 先编译
Jlib模块生成目标文件:ghc -c Jlib.hs - 编译主程序时,只需要指定
Main.hs,GHC会自动找到依赖的Jlib.o:ghc -o Main Main.hs
方式2:一步到位编译
直接把两个源文件传给GHC,它会自动完成编译和链接的全部流程:
ghc -o Main Main.hs Jlib.hs
执行上面任意一种方式,都能成功生成可执行文件,不会再出现重复定义的错误了。
内容的提问来源于stack exchange,提问作者Bercovici Adrian
相关产品推荐
相关产品推荐

