百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

服务器程序从 Windows 系统移植到 Linux/x86_64 平台时总是崩溃?

ahcoder 2025-06-24 11:13 1 浏览

清华大学出版社的《高效 C/C++调试》一书给出了回答:
我们的服务器程序最初是为 Windows 系统开发的, 第一次将它移植到 Linux/x86_64 平台时,它在回归测试中十次会崩溃八次,且仅在多处理器机器上出现这种现象。这种症状强烈地暗示着存在多线程问题。核心转储文件显示,系统库 libc.so 的内存管理器中的函数 malloc_consolidate 内部出现了段错误。考虑到该函数正尝试合并相邻的空闲内存块,我们怀疑应用程序可能以某种方式破坏了堆。

我们打开了内存管理器的调试功能,方法是设置环境变量 MALLOC_CHECK_=2(参见第 10章)。内存调试器捕获到了一个问题—一个内存块被释放了两次,这导致程序崩溃。我们确定了这个内存块上的数据对象,发现它被多个线程共享。然而,对象的所有权是通过引用计数严格控制的,这是共享数据的标准实现方式。当引用计数减少到 0 时,对象将被删除。这个处理在其他平台上得到了良好的执行并且已经通过了全面的测试。那么,为什么在新的平台上会出现问题呢?为了验证引用计数是否按照设计工作,我们在修改对象引用计数的函数中插入了日志语句。

class AtomicLong { public: ... long operator++() throw() { return AtomicIncrement(&mnAtomicLongData); } long operator--() throw() {return AtomicDecrement(&mnAtomicLongData); } ... private: long mnAtomicLongData; }

virtual void AddRef() const throw(void* ipObject, AtomicLong& irRefCount) { RefCountLog("AddRef", ipObject, irRefCount); ++irRefCount; }

virtual void Release(void* ipObject, AtomicLong& irRefCount)const throw() { RefCountLog("Release", ipObject, irRefCount); if (--irRefCount == 0) {

// 这是最后一次引用free(ipObject);

} }

void RefCountLog(const char* ipFunc, void* ipObject, long iRefCount) { FILE* lpFile = GetLogFile(); fprintf(lpFile, "tid= %ld\tFunction=%s\tObjectID=0x%lx”

“\tRefCount=%ld\n",

pthread_self(), ipFunc, ipObject, iRefCount);

// 检索调用者的堆栈跟踪

const int max_stack_depth = 32; void* lTrace[max_stack_depth]; int lTraceSize = ::backtrace(lTrace, max_stack_depth); _ASSERT(lTraceSize > 0);

// backtrace_symbols 分配一块内存来存储符号

char** lpFunctionNames = ::backtrace_symbols(lTrace, lTraceSize); for(int i=0; i<lTraceSize; i++) { _ASSERT(lpFunctionNames[i] != NULL); fprintf(lpFile, "\t[%d] %s\n", i, lpFunctionNames[i]); } }

日志函数记录了发起调用的线程 ID、回溯、对象的地址、当前的引用计数以及对对象的操作。当问题再次出现时,我们在日志文件中得到了一系列的记录。通过脚本解析这些输出,发现 AddRef和 Release 函数被调用的次数与设计时预期的一致,但对象的引用计数并未反映出这一点。这提示我们引用计数器本身(即 AtomicLong 类中的长整数)的递增和递减操作可能存在问题。这个类的递增和递减运算符是通过调用 AtomicIncrement 和 AtomicDecrement 函数实现的,这两个函数都是用汇编语言编写的, 这些函数本应具有原子性和线程安全性。但是,对这些函数的进一步代码审查引发了我们对它们在新平台上执行的正确性的怀疑。经过更严格的单元测试,我们发现在高负载下,这些函数确实存在问题。修复这个错误后,测试就一直运行得很好。

因此,在这种情况下,日志记录的方法帮助我们将问题定位到了引用计数器的原子递增和递减代码上。

相关推荐

卡巴斯基实验室成功将Linux系统的驱动程序移植到“KasperskyOS”

据os.kaspersky.com网站8月8日报道,俄罗斯卡巴斯基实验室启动了一个研究项目,将Linux驱动程序移植到卡巴斯基公司自主研发的操作系统KasperskyOS——这是该实验室创建的“安全...

服务器程序从 Windows 系统移植到 Linux/x86_64 平台时总是崩溃?

清华大学出版社的《高效C/C++调试》一书给出了回答:我们的服务器程序最初是为Windows系统开发的,第一次将它移植到Linux/x86_64平台时,它在回归测试中十次会崩溃八次,且仅在...

Linux系统的移植和裁剪(linux移植lvgl)

本节将嵌入式Linux系统按需求裁剪后移植到ARM处理器中。通过对Linux系统的了解和认识,我们在这里选择Linux4.1.15版本,该版本支持64位处理器,相对于前面几代Linux版本有了更大的提...

搭建RISC-V模拟环境(搭建虚拟环境)

现在RISC-V在主流操作系统上基本都能模拟了,不过我还是觉得Linux下好用。之前在Mac上想用Linux,基本就是在VirtualBox上创建一个虚拟机,从网上下一个Ubuntu的安装iso,安...

CPU虚拟化:陷入和模拟(cpu虚拟模式是什么)

导读:本文摘自于王柏生、谢广军撰写的《深度探索Linux系统虚拟化:原理与实现》一书,重点讨论了虚拟CPU在Guest模式下运行时,由于运行敏感指令而触发虚拟机退出的典型情况。作者:王柏生、谢广军来源...

《模拟山羊》恶搞僵尸主题DLC公布 《DayZ》躺枪!

近日,开发商CoffeeStain为我们带来了一个好消息,那就是奇葩游戏《模拟山羊(GoatSIMulator)》僵尸主题DLC“GoatZ”将于5月7日登陆PC,Mac,Linux,iOS和安卓...

「精品课程」模拟IC设计进阶(模拟ic设计师怎么样)

课程导语模拟集成电路设计最重要的是基础理论知识,基础理论的重要性很多人一开始并没有意识到,工作一段时间,做过几个项目以后就会深有感触。除此之外就是个人的学习能力和分析问题、解决问题的能力,其实这些能力...

跨平台神器:在Linux上轻松运行Windows软件的方法大揭秘!

Wine始于30年前的一个业余爱好项目,当时Windows3.1及其16位API出现了。在一个简单的“HelloWorld”程序之后,它很快就成功地让Solitaire运行起来。...

LAMMPS 模拟教程全新发布,助力科研入门分子模拟世界

https://arxiv.org/html/2503.14020v1本研究发布了8个层层递进的LAMMPS模拟教学教程,并配套开发了专属图形界面LAMMPS–GUI,显著降低了分子模拟的入门门槛。...

Linux趣味命令,每一个都能产生炫酷效果(示例)

Linux趣味命令,每一个都能产生炫酷的效果:cmatrix:模拟《黑客帝国》中的字符矩阵效果。bashCopycodecmatrixfortune:随机显示一句有趣的引语或笑话。bashCopy...

「免费!免费!Chris老师经典模拟课程」CMOS模拟电路设计流程

创芯大讲堂为广大学员发福利各位创芯大讲堂的同学们,即日起,凡当月购买大讲堂课程达到300元的同学可以享受创芯大讲堂全场课程8折优惠,凡当月购买创芯大讲堂课程达到500元的同学可以享受创芯大讲堂全场课程...

Gromacs基本模拟流程(gromacs运行命令)

GROMACS是一个使用经典分子动力学理论研究蛋白质动力学的高端的高效的工具。GROMACS是遵守GNU许可的免费软件,可以从以下站点下载:http://www.gromacs.org,并且可以在l...

国外友人开创Python模拟登陆神库,完美修改它为咱们所用

Awesome-python-login-model是一个国人开发的模拟登陆仓库,在这个仓库上有20几个网站的模拟登陆脚本,你可以基于这个仓库实现的代码做简易的修改,以实现自己的自动化功能。仓库地址...

并发模拟的四种方式+工具,超级实用

原文链接:https://mp.weixin.qq.com/s/jJDJ8YwmzkKS9KvfMamLWA一、PostmanPostman是一个款http请求模拟工具首先演示一下postman最基本...

精选模拟IC设计仿真课程(精选模拟ic设计仿真课程怎么样)

课程介绍本系列课程采用屏幕录制视频及操作解说的形式,注重于模拟芯片设计流程中的电路原理图设计、仿真及优化方法、版图设计、寄生参数提取及后仿真优化等的实际操作,在电路设计过程中学习模拟IC设计和验证方法...