码字不易,转载请注明出处喔
https://blog.csdn.net/newchenxf/article/details/121537539


1 结论

可能你打开这篇文章,是在某个加班的深夜,时间真的不多了,很想回家了,所以我不能先来一堆废话。这次先上结论,以供参考,如果没用,赶紧再找下一家吧…

出现SIGSEGV,是进程执行了一个无效的内存引用。本人目前遇到两次的崩溃,原因不一,这里列举出来。

原因:

  1. 对象在使用时已被释放。
  2. 对象没有初始化。

再展开一点说:

  1. 对象A用局部变量初始化,分配在栈上,函数结束就提前释放了。赋值给其他对象B,B在其他函数引用A时,出现崩溃。
  2. 对象没有被初始化,判空又不为空,使用时崩溃。

解决办法:

  1. 使用智能指针,或者A改成全局变量。
  2. 保证变量在使用前初始化,例如在构造函数初始化。

好了,接下来,详细讨论一下。

2 案例一 对象在使用时已被释放

2.1 问题背景

写好Android C++代码,运行起来崩溃,日志如下:

11-25 15:07:25.546 24467 24527 E glesdemo: ReadMissingBones, m_BoneInfoMap address 0x7e70ed0f88, size 5211-25 15:07:25.554 24467 24527 E glesdemo: GetBoneIDMap, m_BoneInfoMap size 011-25 15:07:25.654 24718 24718 I crash_dump64: performing dump of process 24467 (target tid = 24527)
11-25 15:07:25.655 24718 24718 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-25 15:07:25.655 24718 24718 F DEBUG   : Build fingerprint: 'Xiaomi/sagit/sagit:8.0.0/OPR1.170623.027/V10.2.1.0.OCACNFK:user/release-keys'
11-25 15:07:25.655 24718 24718 F DEBUG   : Revision: '0'
11-25 15:07:25.655 24718 24718 F DEBUG   : ABI: 'arm64'
11-25 15:07:25.655 24718 24718 F DEBUG   : pid: 24467, tid: 24527, name: GLThread 6769  >>> com.chenxf.opengles <<<
11-25 15:07:25.655 24718 24718 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x23d70a00000020
11-25 15:07:25.655 24718 24718 F DEBUG   :     x0   3c23d70a00000020  x1   0000007e70ed0ce0  x2   0000000000000018  x3   3c23d70a00000020
11-25 15:07:25.655 24718 24718 F DEBUG   :     x4   0000007e72355438  x5   0000007e70ed0f68  x6   0000007e70ed11a0  x7   0000000000000000
11-25 15:07:25.655 24718 24718 F DEBUG   :     x8   0000007e72355420  x9   3c23d70a00000020  x10  0000007e70ed0e98  x11  0000007e70ed11a0
11-25 15:07:25.655 24718 24718 F DEBUG   :     x12  0000007e71a44808  x13  0000000000000001  x14  ffffffffffffffff  x15  26204f3d44495400
11-25 15:07:25.656 24718 24718 F DEBUG   :     x16  0000007e72bbbac0  x17  0000007e72b828bc  x18  0000000000000001  x19  0000007e7efa5400
11-25 15:07:25.656 24718 24718 F DEBUG   :     x20  0000007e72b70ee4  x21  000000001384f730  x22  000000001384b8f0  x23  0000007e8f90ab47
11-25 15:07:25.656 24718 24718 F DEBUG   :     x24  0000000000000008  x25  0000007e7efa5498  x26  0000000000000000  x27  0000000000000000
11-25 15:07:25.656 24718 24718 F DEBUG   :     x28  0000000000000002  x29  0000007e70ed0c80  x30  0000007e72b79bfc
11-25 15:07:25.656 24718 24718 F DEBUG   :     sp   0000007e70ed0c70  pc   0000007e72b79bfc  pstate 0000000020000000
11-25 15:07:25.661 24718 24718 F DEBUG   :
11-25 15:07:25.661 24718 24718 F DEBUG   : backtrace:
11-25 15:07:25.661 24718 24718 F DEBUG   :     #00 pc 0000000000028bfc  /data/app/com.chenxf.opengles-bU4sOnN8Yuev-eQs6nf7QA==/base.apk (offset 0x1606000)
11-25 15:07:25.661 24718 24718 F DEBUG   :     #01 pc 0000000000031780  /data/app/com.chenxf.opengles-bU4sOnN8Yuev-eQs6nf7QA==/base.apk (offset 0x1606000)
11-25 15:07:25.661 24718 24718 F DEBUG   :     #02 pc 000000000003e1ec  /data/app/com.chenxf.opengles-bU4sOnN8Yuev-eQs6nf7QA==/base.apk (offset 0x1606000)
11-25 15:07:25.661 24718 24718 F DEBUG   :     #03 pc 000000000003e1b8  /data/app/com.chenxf.opengles-bU4sOnN8Yuev-eQs6nf7QA==/base.apk (offset 0x1606000)
11-25 15:07:25.661 24718 24718 F DEBUG   :     #04 pc 000000000003e16c  /data/app/com.chenxf.opengles-bU4sOnN8Yuev-eQs6nf7QA==/base.apk (offset 0x1606000)
11-25 15:07:25.661 24718 24718 F DEBUG   :     #05 pc 000000000003e110  /data/app/com.chenxf.opengles-bU4sOnN8Yuev-eQs6nf7QA==/base.apk (offset 0x1606000)

一点so的堆栈信息都没有。完全不知道哪一行,这会是什么原因呢?

我先把所依赖的代码,简单列出如下:
第一个类Animator:

class Animator
{public:Animator(Animation* animation){m_CurrentAnimation = animation;}void CalculateBoneTransform(){//省略代码...std::map<std::string,BoneInfo> boneInfoMap = m_CurrentAnimation->GetBoneIDMap();DEBUG_LOGCATE();if (boneInfoMap.find(nodeName) != boneInfoMap.end()){DEBUG_LOGCATE();//省略代码...}}private:Animation* m_CurrentAnimation;};

第二个类Animation

class Animation
{public:Animation() = default;Animation(const std::string& animationPath, ModelAnim* model){m_BoneInfoMap = model.GetBoneInfoMap();//getting m_BoneInfoMap from Model classLOGCATE("ReadMissingBones, m_BoneInfoMap address %p, size %d", &m_BoneInfoMap,m_BoneInfoMap.size());}~Animation(){}inline const std::map<std::string,BoneInfo>& GetBoneIDMap() {LOGCATE("GetBoneIDMap, m_BoneInfoMap size %d", m_BoneInfoMap.size());return m_BoneInfoMap;}private:std::map<std::string, BoneInfo> m_BoneInfoMap;
};

第三个类,初始化上面2个类,并使用:

void Model3DAnimSample::Init() {Animation animation(path + "/model/vampire/dancing_vampire.dae", m_pModel);m_pAnimator = new Animator(&animation);//...
}void Model3DAnimSample::Draw(int screenW, int screenH) {m_pAnimator->CalculateBoneTransform();//省略...
}

2.2 原因分析

我可以本地复现,所以加了很多日志来跟踪,请看最上面的日志前两行:

11-25 15:07:25.546 24467 24527 E glesdemo: ReadMissingBones, m_BoneInfoMap address 0x7e70ed0f88, size 52
11-25 15:07:25.554 24467 24527 E glesdemo: GetBoneIDMap, m_BoneInfoMap size 0

这个m_BoneInfoMap,赋值的时候,有52,到被Animator的CalculateBoneTransform函数调用时,读取值,就变成0了,再进一步使用,就崩溃了。

为啥呢?看了半天,m_BoneInfoMap没有被其他任何地方修改过!!!

再来看看堆栈信息:
11-25 15:07:25.655 24718 24718 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x23d70a00000020

这2个字符代表啥意思呢?
SIGSEGV: 进程执行了一个无效的内存引用。
SEGV_MAPERR: 表示堆栈映射错误。

所以原因出来了:
在Init函数,animation是局部变量,栈上分配的,再赋值给m_pAnimator。 Init函数结束后,animation就无效了,后面m_pAnimator再使用animation,就是栈上的脏数据,所以出现了SIGSEGV

2.3 解决办法

  1. 把Animation做成类的全局变量。即
     m_pAnimation = new Animation(path + "/model/vampire/dancing_vampire.dae", m_pModel);m_pAnimator = new Animator(m_pAnimation);
  1. 用智能指针来创建Animation,即share_ptr。有关智能指针,可以参考:https://blog.csdn.net/newchenxf/article/details/116019535

3 案例二 对象没有初始化

3.1 问题背景

和案例1一样的堆栈

12-27 16:06:13.513 20962 20962 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
12-27 16:06:13.513 20962 20962 F DEBUG   : Build fingerprint: 'Xiaomi/sagit/sagit:8.0.0/OPR1.170623.027/V10.2.1.0.OCACNFK:user/release-keys'
12-27 16:06:13.513 20962 20962 F DEBUG   : Revision: '0'
12-27 16:06:13.513 20962 20962 F DEBUG   : ABI: 'arm64'
12-27 16:06:13.513 20962 20962 F DEBUG   : pid: 20871, tid: 20905, name: GLThread 7653  >>> com.chenxf.opengles <<<
12-27 16:06:13.513 20962 20962 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x72006500640069
12-27 16:06:13.513 20962 20962 F DEBUG   :     x0   0072006500640069  x1   0000000000000302  x2   00000000ffffffff  x3   0000007196a37e0c
12-27 16:06:13.513 20962 20962 F DEBUG   :     x4   003d3d3d3d3d204a  x5   0000008000000080  x6   26415e3d44495400  x7   0000000000008036
12-27 16:06:13.513 20962 20962 F DEBUG   :     x8   0072006500640069  x9   0000000000000001  x10  0000000000000003  x11  00000000000000ff12-27 16:06:13.514 20962 20962 F DEBUG   :
12-27 16:06:13.514 20962 20962 F DEBUG   : backtrace:
12-27 16:06:13.514 20962 20962 F DEBUG   :     #00 pc 0000000000028228  /data/app/com.chenxf.opengles-Xbv907eJgfjlz8Zq9XfKYQ==/base.apk (offset 0x3675000)

3.2 原因分析

没有堆栈,所以也是通过日志,看最后执行到哪里。这里列举一下代码:

class TextSample
{public:TextSample();virtual ~TextSample();virtual void Init();virtual void Draw(int screenW, int screenH);private:Shader *m_pShader;
};TextSample::TextSample() {}void TextSample::Draw(int screenW, int screenH) {if(m_pShader == nullptr)return;DEBUG_LOGCATE();glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glClearColor(1.0, 1.0, 1.0, 1.0);// enable alpha blending// ------------DEBUG_LOGCATE();m_pShader->use();
}

日志崩溃在m_pShader->use()
但奇怪的是,函数的最前面,已经判断为空了!if(m_pShader == nullptr) return;

为啥呢?因为
m_pShader定义了,但是没初始化,所以和JAVA不一样的是,对C++来说,只要生成了TextSample对象,则内部的m_pShader指针就不是为空!

3.3 解决办法

解决办法非常简单,在构造函数,保证初始化指针!

TextSample::TextSample() {m_pShader = nullptr;
}

这也是C++工作和JAVA工作的区别吧!JAVA不用操心指针,某个变量定义好了,不需要初始化也可以,默认为空。

signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)的原因和解决办法相关推荐

  1. Android 10 SurfaceView 奔溃报错signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4

    最近在Android 10 系统上发现SurfaceView 测试的时候奔溃了,10以前的系统测试都会奔溃,在Android 11之后的设备上是正常的. 上错误日志 Native 报错信息 signa ...

  2. A/libc:fatal signal 11(SIGSEGV).code 1, fault addr 0x0 in tid 26488 (VideoEncoder)

    在调试Camera模块:发现相同的代码在厂家提供的环境里边编译.就是ok的,在我们的源码树中编译,将HAL库推进去后.就会signal 11退出. 一.现象 1 F/libc ( 4250): Fat ...

  3. cn.sample.mnn.detect A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid

    mnn报错: cn.sample.mnn.detect A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 ...

  4. 游戏测试问题之:Caused by: java.lang.Error: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000004

    公司开发的小游戏在进行 Monkey 测试时在个别机型一直遇到相同的几个问题,特此记录一下 错误日志如下: Caused by: java.lang.Error: signal 11 (SIGSEGV ...

  5. JNI中Fatal signal 11 (SIGSEGV), code 1的错误.

    这个错,搞了一天才搞定.还是自己对jni不熟. com.viking.myapplication A/libc: Fatal signal 11 (SIGSEGV), code 1, fault ad ...

  6. Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10457e30d996b in tid 5676 (ndroid.settings)

    FROM:http://blogold.chinaunix.net/u3/104564/showart_2091186.html 一.安装交叉编译器  1)交叉编译器使用CodeSourcery提供的 ...

  7. JNI:Fatal signal 11 (SIGSEGV) at 0x00000008 (code=1)错误的一点认识

    最近做的一个东西需要jni去实现,对于一个我这样用惯了java,习惯了debug的人来说,用NDK,使用C/C++去编程是件很苦逼的事情,但是最苦逼的事情在于内存错误发生后如何排查,尤其是 Fatal ...

  8. signal 11 linux,signal 11 (SIGSEGV)错误排查

    jni调试最蛋疼的就是signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4这种错误,爆出来完全不知道是哪句代码造成的,很难定位到问题所在, ...

  9. 集成百度ORC 识别报 Fatal signal 11 (SIGSEGV) (RenderThread) 错误(已解决)

    错误日志: 09-17 16:34:14.052 1422-1519/com.dcqtech.syl A/libc: Fatal signal 11 (SIGSEGV), code 1, fault ...

最新文章

  1. cmd 文本替换_将CMD信息保存为文件
  2. java swing开源组件_Squareness
  3. 如果我是一线技术主管……
  4. 华北电力大学计算机导论试题,华北电力大学 北京 继电保护历年复试试题.doc
  5. mysql 恢复root用户_mysql误删root用户恢复方案
  6. mybatisGenerator 代码自动生成报错 Result Maps collection already contains value for BaseResultMap...
  7. 什么是带内管理 带外管理?(转)
  8. 思考致富 成功法则(二):确定的目的
  9. DS3231时钟模块使用,IIC协议实践。(基于STM32)
  10. 计算机操作系统(汤小丹)慕课版课后题答案第五章:储存器管理
  11. 硬件设计14---什么是预加重与去加重技术?
  12. 上海航芯 | 从STM32F103到ACM32F403的U盘程序移植工程
  13. 内存测试拷机软件,烤机软件 OCCT 更新 9.0.0 版本,新增 CPU/内存跑分测试
  14. 联通将推自有品牌手机沃Phone 基于Android
  15. Oracle安装时先决条件检测失败
  16. 游戏专辑一 3D游戏碰撞之体素内存、效率优化(未完待续10/14)
  17. opencv 中函数的一相关说明,如:cvtColor和cvCvtColor区别
  18. 3dsMax撤销不管用,3dsMax转成多边形之后无法撤回操作,3dsmax的操作步骤一直为空
  19. App制作需要哪些技术?
  20. 如何在Outlook中单击邮件后立即将其标记为已读

热门文章

  1. Norm(范式)的讲解
  2. 2017.08.12(2) 实例:系统登陆
  3. ubuntu11.10 安装谷歌拼音输入法详细步骤
  4. 以太网(Ethernet)通信简单理解
  5. Halcon17完美破解兼容17.12.0.0附破解说明
  6. 《UML和模式应用》读书笔记
  7. CSDN超简单的上传gif动图方法
  8. 对成功的渴望和恐惧——谈心理学中的“瓦伦达效应”和“约拿情结”
  9. uniapp微信小程序证件识别
  10. Linux内核之PCI设备