天天看點

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

一、簡述:    

    在部落客之前的博文《FFmpeg中調用av_read_frame函數導緻的記憶體洩漏問題》中,講述了其中一種使用FFmpeg的api不當導緻的記憶體洩漏的問題。但使用FFmpeg的api不當導緻的記憶體洩漏情況還有很多種,比如FFmpeg申請空間的函數有很多種,如果在申請空間後不調用對應釋放空間的函數,都會造成記憶體洩漏的問題。那我們在還不太熟悉FFmpeg函數的情況下該怎樣找到其導緻的記憶體洩漏的原因呢?我們可以使用一些工具幫助檢查。Windows下檢測記憶體洩漏的工具有好幾種,比如vld(visual leak detector),WinDbg,vs診斷工具等。其中vld隻有在程式結束時才能顯示記憶體洩漏的原因,WinDbg操作又太複雜,是以在這裡部落客推薦大家使用vs診斷工具。對于vs開發的程式,使用vs診斷工具可以幫助檢查其記憶體洩漏問題,而且裡面有一個截取快照的功能,在程式運作過程中,就能找到記憶體洩漏的原因。下面以vs2015為例,講解其使用方法。

二、下載下傳配置FFmpeg的靜态庫

    vs診斷工具隻能定位可執行檔案(exe)和靜态庫裡面的記憶體洩漏問題,無法定位動态庫(dll)裡面的問題。是以要想檢測調用FFmpeg的api導緻的記憶體洩漏問題,我們必須得用FFmpeg的靜态庫,不能用FFmpeg的動态庫。FFmpeg官方隻提供其源碼和動态庫,靜态庫得自己編譯,這裡如果大家不想自己編譯,可以從博文《FFmpeg Windows 各版本靜态庫》中下載下傳靜态庫。下載下傳完後我們就可以建立vs工程,加入FFmpeg的靜态庫了。我們以博文《FFmpeg中調用av_read_frame函數導緻的記憶體洩漏問題》中的程式為例子,講解如何使用vs診斷工具。程式如下所示:

main.cpp

#include <stdio.h>
#include <iostream>
#include <windows.h>
 
extern "C" {
#include "libavformat/avformat.h"
}
 
int main()
{
	const char *path = "video1.mp4"; //需要讀取的本地媒體檔案相對路徑為video1.mp4
	av_register_all();               //初始化所有元件,隻有調用了該函數,才能使用複用器和編解碼器。否則,調用函數avformat_open_input會失敗,無法擷取媒體檔案的資訊
	avformat_network_init();         //打開網絡流。這裡如果隻需要讀取本地媒體檔案,不需要用到網絡功能,可以不用加上這一句
	AVDictionary *opts = NULL;
	AVFormatContext *ic = NULL;
	int re = avformat_open_input(&ic, path, NULL, &opts); //媒體打開函數,調用該函數可以獲得路徑為path的媒體檔案的資訊,并把這些資訊儲存到指針ic指向的空間中(調用該函數後會配置設定一個空間,讓指針ic指向該空間)
	if (re != 0) //如果打開媒體檔案失敗,列印失敗原因
	{
		char buf[1024] = { 0 };
		av_strerror(re, buf, sizeof(buf) - 1);
		printf("open %s failed!:%s", path, buf);
	}
	else  //打開媒體檔案成功
	{
		printf("open %s success!\n", path);
		avformat_find_stream_info(ic, NULL); //調用該函數可以進一步讀取一部分視音頻資料并且獲得一些相關的資訊
		av_dump_format(ic, 0, path, 0);      //輸出媒體檔案的資訊到控制台上
 
		AVPacket *pkt = av_packet_alloc();
		while (1)
		{
			int ret = av_read_frame(ic, pkt);
			if (ret != 0)
			{
				printf("\n--------------------------end--------------------------");
				break;
			}
			//av_packet_unref(pkt);
			Sleep(2);  //睡眠2ms,避免程式執行過快影響觀察效果。
		}
		av_packet_free(&pkt);
	}
	
	if (ic)
	{
		avformat_close_input(&ic);
	}
	getchar();
	return 0;
}
           

我們在vs中建立一個Win32控制台應用程式,添加上述的main.cpp,然後在vs中加入FFmpeg的靜态庫(比如v3.4.2的FFmpeg靜态庫),如下所示:

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題
使用vs診斷工具檢測FFmpeg的記憶體洩漏問題
使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

加入靜态庫完成後,我們編譯程式,使程式可以按照博文《FFmpeg中調用av_read_frame函數導緻的記憶體洩漏問題》中的那樣運作,出現記憶體洩漏問題。

三、使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

我們在vs中按下“F5”快捷鍵->“開始調試”,會出現界面如下圖所示:

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

然後我們在vs診斷工具中按下“截取快照”按鈕在程式運作過程中截取兩個快照,如下圖所示,可以看到第二個快照比第一個快照記憶體增加了。

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

滑鼠左鍵單擊第二個快照,使其高亮顯示,然後點選“檢視堆”。 

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

執行上述操作後,會出現下圖所示的頁面。在“與之比較的對象”這裡選擇“快照#1”,“視圖模式”這裡選擇“類型視圖”。這樣就會顯示快照2比快照1增加的記憶體大小。我們可以看到在“未解析的配置設定”這行顯示大小差異為5340933位元組,

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

然後滑鼠輕按兩下“未解析的配置設定”這一行。

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

在出現的下圖所示的界面中,輕按兩下其中的一行。

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

選中“ConsoleApplication2.exe!main() - 行 32”這行,單擊滑鼠右鍵,在出現的右鍵菜單中點選“轉到源代碼”。

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

然後我們可以看到vs自動幫我們定位到“int ret = av_read_frame(ic, pkt);”這行了,該行正是導緻程式記憶體洩漏的原因。

使用vs診斷工具檢測FFmpeg的記憶體洩漏問題

至此,我們已經學會了使用vs診斷工具檢測FFmpeg記憶體洩漏問題的方法。