一种signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)的原因

Posted 长江很多号

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一种signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)的原因相关的知识,希望对你有一定的参考价值。

1 问题背景

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

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


11-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 class
		LOGCATE("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 原因分析

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

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

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

4 总结

出现SIGSEGV,是进程执行了一个无效的内存引用。可以重点看一下是不是某个对象已经被释放了。本文就是因为对象用局部变量创建,分配在栈上,所以被提前释放了,后面还想使用就出问题了。

以上是关于一种signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)的原因的主要内容,如果未能解决你的问题,请参考以下文章

Fatal signal xx (SIGSEGV) at

我的C/C++语言学习进阶之旅NDK开发运行的时候出现错误signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x940a2e48

我的C/C++语言学习进阶之旅NDK开发运行的时候出现错误signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x940a2e48

我的C/C++语言学习进阶之旅NDK开发运行的时候出现错误signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x940a2e48

Application received signal SIGSEGV

为啥启用 NEON SIMDization 时 Android 会崩溃?信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR)