服务端段错误

mysql-odbc驱动8.0.12 MYSQL ODBC驱动 32/64位 亲测有效,安全无毒,放心使用! 立即下载
之所以有上篇文章,是因为那个方法就是我在解决这篇文章中的问题时使用的.为了避免篇幅过大,所以分成了两篇专栏.

先说说这次崩溃吧,第一次崩溃是晚上7点多,运营同学发来了bt(gdb命令,就是backtrace stack),如下图:

看见这种调用栈我的第一想法就是栈越界了,栈越界我一点都不担心,比什么野指针写坏堆好解决多了,因为离"犯罪现场"近啊.

上一篇专栏里说过,无法回溯调用栈有可能是"调用栈链表头"被写坏了,我们先看看栈顶附近的内容是什么:

不知道你是否发现了,栈顶向下的内容是0x30303039这样的东西,这东西一看就像字符串,别问我为什么,这是经验加敏锐的直觉,哈哈.那我们看看这是什么字符串:你看,还真是字符串,于是我找了下这个字符串的可能来源,发现这东西是聊天窗口里的内容.怎么是聊天窗口里的内容呢?是因为聊天内容在某些情况下过长了?于是检查聊天相关的代码,发现的确有一处有隐患.那我们就试着利用这处隐患,看看是否能重现这次崩溃.

无论我们发什么聊天内容,都无法导致服务端崩溃,最后我们放弃了,把这处隐患改正了.此时外服服务端又开始崩溃了,而且几分钟崩溃一次,必须快速定位到出问题的地方,然后尝试动态修复,否则玩家没有办法游戏了.

于是机智的我想到了一个撞运气的方法,我先来简单描述下栈里的内容:

贴出这张图的时候,我已经被自己的机智折服了.这个图大家熟悉吧,我用这个东西来解释一下栈的运行时状态:

  1. 我们把它当作栈的保留大小,在msvc下默认是1MB,linux上看ulimit里的配置,默认情况是8MB
  2. 我们把它当作栈的提交大小(这里就不详细解释了,等有机会写一篇专栏介绍下内存相关的东西再解释)
  3. 这里是当前的esp的值,也就是栈顶指针
  4. 这里是栈底
好了,图介绍完了,我们来播放一首音乐,然后你会发现图中的3会随着音量的大小上下振动,这正是我想要的效果.因为程序在运行时,栈顶指针就像图中的3所指的绿色柱形图一样,上下振动.当调用深度比较深的时候,栈顶指针就越靠近上端,当函数返回时,栈顶指针就会向下移动.

好了,现在我们的程序崩溃了,栈顶指针停在了3所指向的位置,那3上面的内容是什么呢?我们看下面的示例代码:

int func()
{
   ......
   func1();
   return 0; 
}

int func1()
{
    ....
    func2();
    return 0;
}

假设在func返回的时候,崩溃了,那他一定调用过func1,func1里再调用func2的时候,就会把返回地址压入栈,而这个返回地址,就是func1 + offset.也就是说,当在func返回的时候崩溃了,那么栈里很有可能会保留func里刚刚调用过的函数产生的栈信息,因为栈顶指针在向下移动的时候并不会清理栈里面的内容.

那好,我们就看看当前栈顶(esp)上面的信息.(处于保密原因,这里就不贴相关的栈里的信息了).查看方法依然是用我上篇专栏里提到的bts扩展指令,只要将起始地址设置为esp - 1000就可以了.

通过分析输出的信息发现,几次崩溃的core文件内,在栈顶上方保留的栈信息都是一模一样的,都调用了FuncA函数,连偏移都一样,而这个FuncA函数是活动A里的,然后我和同事以及领导商量了一下,决定在崩溃的大区中关闭一个线的A活动,如果不再崩溃,那问题就锁定在A活动上了.

说干就干,动态reload了配置表格,停止了一个线的A活动,结果在长达几个小时,其他线各种崩溃的情况下,竟然真的不崩溃了.于是把其他线的A活动也关闭了.

那么接下来的问题就是查查到底A活动出了什么问题,我和几个同事翻遍了svn log,也没看出一点问题,本来这次更新的内容就不多,和这个A活动相关的代码就一条,已经确认N次没有问题了.那是怎么回事呢?这个A活动和聊天有什么关系呢?

此时我又整理了一下思路,首先栈里出现了字符串,这很有可能就是越界.曾经我一度怀疑和A活动没有关系,关闭A活动不崩溃只是巧合而已,因为几个core文件里,栈顶附近的内容都是聊天字符串,应该是聊天的锅.但是我们有没有办法利用聊天来重现这次崩溃,可是聊天内容就是出现在了栈里.

为了搞清楚问题,就有了上篇专栏的内容,我用上篇专栏的方法,找到了几个main函数开始的调用栈,然后分析了一下其中的Receive函数的参数,这个Receive的参数就是从客户端收到的数据,根据协议分发到不同的函数去执行.

我分析了一下包结构,是这样的:

struct Packet
{
    BYTE byCmd;
    BYTE bySubCmd;
    WORD wData[3];
    CHAR szData[1024];
}

这个packet里的byCmd和bySubCmd决定了这个包的类型,正是参加A活动需要发送的包,而其中的szData,正常情况下应该是玩家的名字,而玩家的名字长度在服务端是有限制的,是32,但是奇怪的是,这个Recieve里收到的这个Packet,szData竟然是聊天内容,而服务端里对这个szData的长度没有进行合法性判断,直接memcpy(dst, szData, strlen(szData),导致把栈写坏了(这个包是个通用包,所以szData是1024,只不过不同的包在服务端用到的长度是不一样的,这个A活动用到的长度就必须小于等于32).

原来如此,此时就完美解释了为什么栈里有聊天信息,关闭A活动就不崩溃了,原来是玩家在参加活动发包的时候,把聊天内容写到了szData里,然后服务端判断不严谨,导致服务器崩溃.于是修改服务端代码,判断一下长度,然后更新出去,发现服务端不崩溃了.

好了,接下来的疑问就是为什么客户端会把聊天内容当作名字发过来了,是只写坏了szData,还是其中的byCmd,bySubCmd,wData[3],szData都是错的,恰好导致这个包与参加A活动的协议头相同?

哎,N个人加班检查客户端代码,也没有发现到底是怎么回事,查看内存里的信息发现wData[3]里的内容也是错的,wData里的内容和szData里内容还不是连续的聊天信息.并没有想出如何才能发出这样的包,于是我在客户端发包的地方加了这样一条代码:

int Send(...)
{
    ....
    if(byCmd == 40 && bySubCmd == 120 && strlen(szData) > 32)
    {
        DebugBreak();
    }
}

既然你发非法包,那你就崩溃一下,然后生成dmp文件,我看dmp文件里的调用栈好了.

PS:其实这次关闭活动的方法有一定运气成分,熟悉调用栈的同学应该知道,上面的函数未必就是刚刚调用过的函数,很有可能是很久之前调用的,只不过从那以后并没有更深的调用来覆盖它.但是调试core文件这种事情,本来就和运气有很大关系,我每次解决崩溃后,都有一种我运气真好的感觉.

避开这些坑!用Python ReportLab生成PDF时字体处理与中文排版的5个关键技巧 本文针对Python ReportLab库在PDF自动化生成中常见的中文排版难题,提供了五个关键技巧。内容涵盖字体注册的稳健策略、段落样式的精细控制、表格内中文的换行对齐、页面布局管理以及性能优化,旨在帮助开发者彻底解决中文乱码、排版错位等问题,生成专业美观的PDF文档。 阅读详情

相关推荐

电磁场可视化

电磁场可视化 如题,做了电磁场可视化这么久了,也是颇有些心得了,简单描述一下怎么做这个项目的。 开始时是从最基本的OpenGL开始做的,必不可少的翻了许多的文献,后来是直接在unity中做,发现效果挺好,而且可控性强好多。反复琢磨后,发现可视化的渲染,有几种思路,第一就是用linerender,画线的方法,另一种就是用shader。 第一种我通过unity自带的linewave插件可以做到 详细的就是,linewave插件可以轻松画出曲线等,并且可以添加碰撞,控制频率幅度长度等一切的条件数值,而且令人惊喜

weixin_43979140的博客 1670

《Linux杂记》Linux环境下段错误的产生原因及调试方法小结

1段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址、访问了系统保护的内存地址、访问了只读的内存地址等等情况。这里贴一个对于“段错误”的准确定义(参考Answers.com): A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer softw

不问归期的博客 1819

四足机器人机械结构设计:从腿型到驱动的全面解析

本文全面解析了四足机器人机械结构设计的核心要点。资深工程师老张深入探讨了并联腿与串联腿的选型策略、不同腿型布局对稳定性的影响,并详细对比了皮带轮与连杆驱动方式的优劣。文章结合实战经验,强调了足端设计、材料选择及整体结构轻量化等关键细节,为机器人开发者提供了从理论到实践的宝贵指导。

assembly8low的博客 632

在统信操作系统下达梦8数据库配置unixodbc遇到的三个问题

本文介绍了在ARM+统信操作系统的机器上安装unixodbc适配达梦数据库遇到的三个问题,其中第一个问题是安装版本与机器环境不兼容,通过官网下载最新版本解决,第二个问题是由于找不到libodbcinst.so库文件,通过设置路径或拷贝libodbcinst.so到相关路径解决,第三个问题是由于配置的odbc.ini文件目录不对导致,调整目录即可。

老猿Python 1442

Altium Designer (AD) 设计软件高频面试题及参考答案(3万字长文)

在Altium Designer(AD)中,设计复用是一种关键的策略,它允许设计师在多个项目中重复使用经过验证的设计元素,如原理图符号、PCB布局、元器件封装和设计规则集。在Altium Designer (AD) 中,手动布线和交互式布线是PCB设计中常见的两种布线模式,它们提供了设计师对布线路径的直接控制,特别是在处理复杂或关键信号路径时尤为有用。在Altium Designer (AD) 中进行电路级仿真是一项重要的设计验证步骤,它允许设计师在实际制造之前对电路的行为进行预测和分析。

大模型大数据攻城狮的专栏 4782

【AUTOSAR-RTE】-1-聊一聊RTE(Run-Time Environment)

RTE(Run-Time Environment)是AUTOSAR ECU架构的核心。

「汽车电子助手」的博客 6501

Linux下程序产生“段错误”的原因及其解决办法

Linux下程序产生“段错误”的原因及其解决办法 产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址。 一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,它是一个48位的寄存器,其中的32位是保 存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序在cpu中的运行级别,指向的gdt是以64位为一个单 位的表,在这张表中就保存...

chenzhjlf的专栏 8130

1、微软 Intune 全面指南:配置、管理与自动化

本文全面介绍了微软 Intune 的配置、管理和自动化操作,涵盖用户与设备管理、安全策略设置、跨平台应用部署、合规性监控及报告分析等内容。通过详细的操作步骤、自动化脚本示例和流程优化建议,帮助技术人员高效掌握 Intune 在混合办公环境中的实际应用,并展望其未来发展趋势。

ii567的博客 357

[记录问题]安卓客户端发送指令给树莓派服务端,服务端出现段错误

文章目录问题总结 参考文章:https://blog.youkuaiyun.com/liuye066/article/details/83647350?utm_source=app&app_version=5.3.0&code=app_1562916241&uLinkId=usr1mkqgl919blen 问题 出现段错误 产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址. 解决方法: 利用gdb逐步查找段错误: 首先我们需要一

mantouyouyou的博客 311

【异常】Claude Code CLI工具 模型加载异常 /init报错排查与完整解决方案 There‘s an issue with the selected model (glm-5). It

此类跨厂商模型配置报错,核心诱因是API生态的兼容性不匹配。优先使用工具原生支持的模型体系,可快速解决90%以上的同类报错;若需跨厂商使用目标模型,需完成API端点、鉴权密钥、模型ID的全链路适配,确保全流程配置合规,即可完成异常修复。

奶爸的编程之路,也就一周冷个三天 3699

适航文章汇总:知识体系全面梳理

无论您是行业新手还是经验丰富的专业人士,都可以通过本篇文章快速查找相关资料,提高对适航认证、机载系统、软件及硬件等领域的理解。本部分详细解析ARP 4754A、ARP 4761、DO-178C、DO-254等核心标准,并介绍其在机载系统开发中的应用。介绍FAA、EASA、CCAR等主要航空管理机构的适航规章体系,并说明各类飞行器(如固定翼、旋翼机、无人机等)的适航要求。本部分还探讨硬件设计、验证与确认过程中的挑战。从系统架构设计到机载设备的集成与管理,本部分介绍机载系统的研发体系及适航管理的最佳实践。

qq_41854911的博客 1448

【问题记录】Ubuntu 22.04 环境下,程序报:段错误(核心已转储)怎么使用 core 文件和GDB调试器 解决?

首先要确定核心转储文件的生成路径和大小限制。然后使用调试器(如 GDB)来分析核心转储文件和堆栈跟踪信息后,修复代码中导致“段错误”的原因。

weixin_43729127的博客 2万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

在linux上写关于socket客户端程序时为什么会出现段错误呢,socket 接收数据时出错(段错误)...

socket接收数据时出错(段错误)(2012-04-10 23:26:35)标签:数据杂谈socket接收数据时出错(段错误)大家好,又是我来问linux下socket问题了。我那个UPD的程序终于改好了,现在客户端跟服务器端都可以正常编译运行了。但是,问题又来了...我先运行服务器端,正常,再运行客户端向服务器端发送数据,这时服务器端就自动报错退出了,提示是段错误。请问是不是因为接受数据的内...

weixin_42299679的博客 618

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

关于调试IPC设备的小结

上周负责测试一款PEA(边界防范)算法,在这里想做个小结,希望在以后的调试中遇到问题时能有用。 周三,我收到了里面烧写好算法程序的IPC(网络摄像头)设备。设备里面有服务端程序,另附了一个客户端测试程序给我,以及一些算法的PDF。开始进行测试: 首先,用客户端软件连接设备的服务端程序,但怎么都连不上。以为网络没连上,就在本机Ping设备的IP地址,反应没问题,可以通。后来想想,应该是设备的服务

cjsycyl的专栏 1844

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

HoRain云--Linux下C/C++服务端崩溃排查全攻略

本文提供了Linux下C/C++服务端崩溃排查的完整指南。首先介绍了调试环境准备,包括GDB安装、编译选项设置和CoreDump配置。重点讲解了使用GDB的详细步骤:从启动程序、复现崩溃到分析调用栈和变量值。针对常见崩溃原因(空指针、内存越界、多线程竞争等)给出了具体排查方法,并推荐了Valgrind、AddressSanitizer等辅助工具。文章还包含预防措施建议和实际案例分析,最后总结了核心排查流程:编译调试→GDB分析→调用栈定位→源码修复。通过系统化的方法帮助开发者快速定位和解决服务端崩溃问题。

2401_86544677的博客 1084

一个问题

调试一个socket程序,服务器端总是显示有内存错误,通过core文件分析,发现fclose时调用free,会引发一个段错误,难道函数库的bug让哥们我遇到了,不至于吧,于是查看fclose系统调用,左看右看愣是没找到。突然想到这个函数在客户端也调用了,也没出什么bug,!!!!!!!!曾经有一个bug,在客户端调试的时候改了,当时也懒,没改服务端的代码,结果查了半天才找到。 有没

340

【问题记录】裸指针和智能指针

别让裸指针和智能指针同时管理一个对象

Pursue quality, not quantity. 405

线程池出现段错误

经过排查发现相同的连接套接字会被处理多次,在发送完图片后会删除相应图片,因此最终导致段错误。不使用线程池发现请求队列的加锁没有问题,因此问题定位到线程池部分。 最终发现是线程池中加速力度不够,在往线程池中添加任务时,一部分代码没有在锁内,导致出错。 另一个错误是传递给线程池中工作线程的参数是局部变量的指针,当传递给工作线程时他没有能够立即执行,有其他线程抢占,因此该内存地址中的值已经变化了,获

sinat_26331725的博客 1252

CentOS 7部署CABAL EP8服务端:从系统配置到进程协同的完整指南

在Linux服务器部署中,操作系统环境配置与依赖库管理是确保应用稳定运行的基础。CentOS 7作为经典的企业级发行版,其稳定的内核和广泛的软件兼容性,为部署各类服务端应用提供了可靠平台。通过配置静态IP、调整SELinux与防火墙策略,以及优化Yum源,可以构建一个高效、安全的运行环境。对于依赖特定运行时库的应用程序,如需要32位库支持的老旧游戏服务端,使用`yum install glibc.i686`等命令安装兼容库是关键步骤。这些技术实践不仅解决了程序启动时的依赖问题,也体现了系统环境适配在软件部署

weixin_33738578的博客 337

TCP/IP调用accept报错:Segmentation fault (core dumped) 。。。解决方法

Linux网络编程之Tcp(内含服务器、客户端代码实例)https://blog.youkuaiyun.com/QQ1402369668/article/details/86090092 运行上述事例代码,服务端在accept函数调用等待后,client端发送字符串,服务端的accept报错:Segmentation fault (core dumped)。 Linux基于TCP/IP简单的客户端、服务器通信程序实例 https://blog.youkuaiyun.com/fucangzxx/article/...

逐渐成长的coder 1181

进程间通信2

设计一个本机聊天功能 利用共享内存 #ifndef _CHAT_H #define _CHAT_H struct Msg { char name[20]; char msg[1024]; pthread_mutex_t mutex; pthread_cond_t cond; }; #endif #include "head.h" #include "chat.h" struct Msg *share_memory = NULL; int main() { i

aMonstere的博客 157

利用linux信号机制调试段错误(Segment fault)【转】

转自:http://blog.youkuaiyun.com/ab198604/article/details/6164517 版权声明:本文为博主原创文章,未经博主允许不得转载。 在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止。如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过串口...

weixin_34236869的博客 204

记录一次卑微找bug

写了一个多线程TCP通信客户端,在测试的时候,发现只要有一个任意一个客户端退出,服务端就会崩溃退出导致整个服务器崩溃!我找了好久好久,一直以为是线程池写的有问题,导致某个地方越界访问了。最后在强迫症修改代码格式的时候,改到了Task.hpp文件,发现了这句代码,这里一开始是写着返回值的,后面没用到返回值,就把return语句注释掉了,但是没有修改函数的返回值!导致一直出bug,所以一定要规范写代码啊啊啊!使用telnet来进调试,介绍如下。

m0_61780496的博客 128
上一篇: 一种处理栈越界的方法
下一篇: Perf 简介 性能调试工具
linux_vae
博客等级 码龄15年 48粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值