您的位置:首页 > 大数据 > 人工智能

死循环问题窥视系统main函数初始化之前操作

2016-04-09 00:01 441 查看
>

之前一个死锁问题,说也奇怪,代码没有修改,没有集成,没有crash,没有卡顿,突然发现有个功能无法用了。后来发现是子线程死循环了,导致功能的没有执行。从这个Bug,提了一个问题,在main函数之前,系统你在做什么?+load, 全局对象初始化,静态对象初始化,这些操作时序又是如何的呢?

总结结论

对于XOS来说,系统main函数之前,会做大概如下四件事情

+ _ attribute _((constructor))

+ +(void)load;

+ 全局变量初始化

+ 静态变量初始化

那他们的时序是: 这个时序很重要

load –> _ attribute _((constructor)) –> 全局变量初始化 –> 静态变量初始化

调用 load – 图片:



调用_ attribute _((constructor))– 图片:



调用全局变量初始化 图片:



调用静态变量初始化 图片:



描述死锁bug

简化死锁代码如下:

@implementation FYAsserm

+ (void)load
{
//一个逻辑,触发好多个关联库,最后调到
DemoCPlusClass对象的m_lock.create() ,m_lock.lock()
}

@end

class DemoCPlusClass
{
public:
static TMutex m_lock;
};

/** 构造函数 */
TMutex::TMutex()
{
memset(&m_hMutex, 0, sizeof(pthread_mutex_t));
}

/**
* 用指定的的名称创建一个新的互斥区
*/
void TMutex::Create(bool isRecursive /*= V_TRUE*/)
{
size_t type = PTHREAD_MUTEX_NORMAL;
if (isRecursive) {
type = PTHREAD_MUTEX_RECURSIVE;
}
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, (int)type);
pthread_mutex_init((pthread_mutex_t*)&m_hMutex, &attr);
}

/**
* 锁定TMutex对象
*      @param uiWaiting [in] 等待时间(单位:毫秒)
*
*      @return 成功返回true,否则返回false
*/
bool TMutex::Lock(size_t uiWaiting)
{
if(uiWaiting == T_INFINITY_WAIT)
{
while(pthread_mutex_trylock((pthread_mutex_t*)&m_hMutex) != 0)
{
TSleep(10);
}

return true;
}
else
{
size_t iWaiting = uiWaiting;

while(pthread_mutex_trylock((pthread_mutex_t*)&m_hMutex) != 0)
{
iWaiting -= 10;

if(iWaiting <= 0)
return false;

TSleep(10);
}

return true;
}
}


下面是TMutex类的声明

/*
*  类名: TMutex
*  功能: 互斥锁对象
*/
class TMutex
{
public:

/** 构造函数和析构函数 */
TMutex();
TMutex(TBool bInitLock);
virtual ~TMutex();

public:

/**
* 用指定的的名称创建一个新的互斥区
*/
void Create(bool isRecursive = true);

/**
* 锁定TMutex对象
*      @param uiWaiting [in] 等待时间(单位:毫秒)
*
*      @return 成功返回true, 否则返回false.
*/
bool Lock(size_t uiWaiting = T_INFINITY_WAIT);

/**
* 释放TMutex对象
*      @return 成功返回true, 否则返回false.
*/
bool Unlock();

/**
* 得到TMutex的句柄
*  @return 事件的句柄
*/
THandle GetHandle();

protected:

bool                m_bInit;
pthread_mutex_t     m_hMutex; // linux下需要此结构体
};


原因说明:

在main函数执行之前:

1. 先调用了,+load函数

2. 再静态变量初始化,调用对象构造函数

由于在+load函数间接调用中,先调用了m_lock.create(), 此时函数调用时序错乱了(按道理应该先调用对象构造函数,在调用对象的方法函数,但是此时时序是相反的)

这样导致,先创建 pthread_mutex_t m_hMutex; // linux下需要此结构体对象成员变量,然后构造函数又把该成员变量清零。

最终导致,下一次调用该对象的lock方法时,发生死锁

bool TMutex::Lock(size_t uiWaiting)
{
if(uiWaiting == T_INFINITY_WAIT)
{
while(pthread_mutex_trylock((pthread_mutex_t*)&m_hMutex) != 0)  //死循环 -- 返回值为22,表示无效锁
{
TSleep(10);
}

return true;
}


对于每个技术细节,都要全面理解,之前我只知道main函数之前系统操作,但是没有深入挖掘了解时序信息,最后导致这个bug。所以深深感觉到『匠心长存』这几个字的含义,踏实做好各个环节。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios