【genius_platform软件平台开发】第九点:记一次前置声明引起的异常数据内存malloc异常行为0x80000000

在开发gp软件平台时,周五组内小伙伴在开发硬解码时发现H264解不出流了,奇了怪了。由于周五请假了,小伙伴辛辛苦苦排查了一天。

具体的代码组织结构如以下:

CGpH264FrameProcess .h

#ifndef __GP_H264_FRAME_PROCESS_H
#define __GP_H264_FRAME_PROCESS_H

#include "GpFrameBaseProcess.h"
#include "GpH264Decode.h"

//
// H264帧处理
class CGpH264FrameProcess : public CGpFrameBaseProcess
{
public:
    CGpH264FrameProcess();
    virtual ~CGpH264FrameProcess();

public:
    // H264解码后相应函数
    virtual INT32 onFrame(CGpFrame* pFrame);

    // 帧处理函数
    virtual INT32 ProcessFrame(void* pData = NULL);

private:
    CGpH264Decode* m_pH264Decode;
};

#endif

CGpH264FrameProcess .cpp

#include "Base/Thread/GpFrameProcessThread.h"
#include "GpH264FrameProcess.h"

//
//
CGpH264FrameProcess::CGpH264FrameProcess()
{
    LOGMSG("CGpH264FrameProcess::CGpH264FrameProcess...");

    // 等待耗时统计
    TimePoint nTotalCostTm = currentTime();

    // 设置运行
    m_bWorking = true;

    // 设置type
    this->setType(FrameProcessType_H264);

    // H264解码对象
    m_pH264Decode = new(std::nothrow) CGpH264Decode();
    CHECK(m_pH264Decode);
    CHECK(m_pH264Decode->setFrameProcess(this));
    CHECK(m_pH264Decode->initCodec());

    LOGMSG("CGpH264FrameProcess::CGpH264FrameProcess is suc... nTotalCostTm=[%u]", (currentTime() - nTotalCostTm).count());
}

//
//
CGpH264FrameProcess::~CGpH264FrameProcess()
{
    LOGMSG("CGpH264FrameProcess is destroyed...");

    // 等待耗时统计
    TimePoint nTotalCostTm = currentTime();

    // 释放线程资源
    this->releaseFrameProcThread();    

    // 最后释放m_pH264Decode
    SAFE_DELETE(m_pH264Decode);

    LOGMSG("CGpH264FrameProcess is destroyed... nTotalCostTm=[%llu]", (currentTime() - nTotalCostTm).count());
}

//
//
INT32 CGpH264FrameProcess::ProcessFrame(void* pData /*= NULL*/)
{    
    CGpFrameProcessThread* pThread = static_cast<CGpFrameProcessThread*>(pData);
    CHECKI(pThread);

    CGpFrame* pFrame = this->takeFirst();
    if (!pFrame || pFrame->isEmpty())
    {
        // 阻塞等待,后续有空时测试下效率
        /*
        * 1.锁导致上下文切换开销很大,导致帧率30~10帧
        */
        //std::unique_lock<std::mutex> ulock(m_Mtx);
        //m_Cond.wait(ulock);
        //printf("CGpH264FrameProcess m_Cond.wait(ulock)\n");
        msSleep(10);
        return ReturnCode_Empty;
    }

    GpFrameType frameType = pFrame->getFrameType();
    CHECKI(frameType == FRAME_TYPE_H264);

#if _TEST_H264_FRAME_MEMORY_LEAK
    // 释放pFrame
    SAFE_DELETE(pFrame);
#else
    // 可以通过配置文件或者设备端 优先设置
    if (m_pH264Decode->allocateSpace(pFrame->getWidth(), pFrame->getHeight()))
    {
        m_pH264Decode->decode(pFrame);
    }

    // 释放pFrame
    SAFE_DELETE(pFrame);

#endif

    return ReturnCode_Success;
}

//
//
INT32 CGpH264FrameProcess::onFrame(CGpFrame* pFrame)
{
    CHECKF(pFrame); 
    CHECKF(m_pFrameProcessCenter);
    m_pFrameProcessCenter->outputFrame(pFrame);
    return ReturnCode_Success;
}

CGpH264Decode.h

#ifndef __GP_H264_DECODE_H
#define __GP_H264_DECODE_H

#include "Base/Common/GpFrame.h"
#include "GpFrameBaseProcess.h"

#ifdef __cplusplus
extern "C"
{
#endif
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_qsv.h"
#include "libavutil/mem.h"
#include "libavformat/avformat.h"
#ifdef __cplusplus
}
#endif

//
/*
* H264解码
* 先调用allocateSpace分配空间,再调用decode实现实现解码
*/
class CGpH264Decode
{
public:
    CGpH264Decode();

    ~CGpH264Decode();

public:
    //...

    /*
     * 前期使用的是CGpFrameBaseProcess*, 后期修改为:注意使用基类指针,不要用前置声明,否则会出现异常错误情况
     */
    CGpFrameBaseProcess* m_pFrameProcess;
};

#endif

CGpH264Decode.cpp

#include "GpH264Decode.h"
#include "GpH264FrameProcess.h"

//
//
CGpH264Decode::CGpH264Decode():
m_pCodec(NULL), 
m_pAVCodecParserContext(NULL), 
m_pAVCodecContext(NULL), 
m_pAVPacket(NULL), 
m_pAVFrame(NULL), 
m_srcPixelForamt(AV_PIX_FMT_YUV420P), 
m_dstPixelForamt(AV_PIX_FMT_RGB24), 
m_pSwsContext(NULL), 
m_pBufferRGBFrame(NULL), 
m_bufferLen(0), 
m_pRGBAVFrame(NULL),
m_pFrameProcess(NULL),
m_dstWidth(0), 
m_dstHeight(0),
m_pFrame(NULL)
{
 
}

CGpH264Decode::~CGpH264Decode()
{
    // 等待耗时统计
    TimePoint nTotalCostTm = currentTime();

    freeCodec();

    LOGMSG("CGpH264Decode is destroyed... nTotalCostTm=[%llu]", (currentTime() - nTotalCostTm).count());
}

bool CGpH264Decode::allocateSpace(INT32 width, INT32 height)
{
   //...
}

bool CGpH264Decode::initCodec()
{
    av_register_all();

    // 获取解码器
    m_pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
    if (!m_pCodec)
    {
        LOGERROR("avcodec_find_decoder is error. m_pCodec=[NULL]");
        return false;
    }

    // 根据AVStream的id找到对应的parser,所有的parser在libavcodec/all_codec.c中注册,
    m_pAVCodecParserContext = av_parser_init(m_pCodec->id);
    if (!m_pAVCodecParserContext)
    {
        LOGERROR("av_parser_init is error. m_pAVCodecParserContext=[NULL]");
        return false;
    }
    //在打开解码器后初始化parase
    m_pAVCodecParserContext->flags |= PARSER_FLAG_ONCE;

    // 配置解码器
    m_pAVCodecContext = avcodec_alloc_context3(m_pCodec);
    if (!m_pAVCodecContext)
    {
        LOGERROR("avcodec_alloc_context3 is error. m_pAVCodecContext=[NULL]");
        return false;
    }

    // 该函数用于初始化一个视音频编解码器的AVCodecContext
    if (avcodec_open2(m_pAVCodecContext, m_pCodec, NULL) < 0) //not thread safe
    {
        LOGERROR("avcodec_open2 is error.");
        return false;
    }

    /* 注意在此处就出现了异常情况:详情见下图!!!!*/
    //分配一个结构体大小的内存
    m_pAVPacket = av_packet_alloc();
    if (!m_pAVPacket)
    {
        LOGERROR("av_packet_alloc is error. m_pAVPacket=[NULL]");
        return false;
    }

    // 分配帧内存,用来保存帧,存储从packet解码后的帧数据
    // m_pFrame分配空间,该函数并没有为AVFrame的像素数据分配空间,需要使用av_image_fill_arrays分配
    m_pAVFrame = av_frame_alloc();
    if (!m_pAVFrame)
    {
        LOGERROR("av_frame_alloc is error. m_pAVFrame=[NULL]");
        return false;
    }

    m_pRGBAVFrame = av_frame_alloc();
    if (!m_pRGBAVFrame)
    {
        LOGERROR("av_frame_alloc is error. m_pRGBAVFrame=[NULL]");
        return false;
    }
    
    return true;
}

编译没有问题,但是在执行的时候发现指针和函数调用异常,如图所示:

 

会出现分配的内存不可读

会出现指针为:0x80000000的地址

内存堆栈信息已经完全被破坏掉了,经排查把涉及到前置类型声明的去掉,并用接口基类进行声明数据成员,在需要的CPP文件进行头文件的include操作,该问题得到解决。不知道为何会出现这种异常行为,是使用出错还是编辑器出错!!!

居然之前还遇到了一次0x00000000的malloc地址还可以继续执行->操作!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值