๋ฐ˜์‘ํ˜•

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์™€ ๊ด€๋ จ๋œ ํฌ์ŠคํŒ…์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

[๋””๋ฒ„๊น…] ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์™€ ์ ๊ฒ€ํ•˜๋Š” ๋ฐฉ๋ฒ• ์†Œ๊ฐœ

 

[๋””๋ฒ„๊น…] ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์™€ ์ ๊ฒ€ํ•˜๋Š” ๋ฐฉ๋ฒ• ์†Œ๊ฐœ

์†Œ๊ฐœ Unmanaged Code์ธ C++์€ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น๊ณผ ํ•ด์ œ๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ํ•ด์ œ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด, ๊ทธ๋Œ€๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ ์œ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” ์–ด๋–ป๊ฒŒ ์ ๊ฒ€ํ• ๊นŒ์š”? ์ ..

luckygg.tistory.com

MFC Dialog ์˜ˆ์‹œ

MFC Dialog ํ”„๋กœ์ ํŠธ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๊ณ ์˜๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Main Dialog์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ byteํ˜• ํฌ์ธํ„ฐ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

byte* m_pBuffer;

๊ทธ๋ฆฌ๊ณ  ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด 100byte๋ฅผ ๋™์  ํ• ๋‹น ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

void CMFCApplication1Dlg::OnBnClickedButton1()
{
	m_pBuffer = new byte[100];
}

F5๋กœ ๋””๋ฒ„๊ทธ ๋ชจ๋“œ๋กœ ์‹คํ–‰ ํ›„ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜๋ฉด, ์ถœ๋ ฅ ์ฐฝ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด Memory Leak ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Memory Leak์ด ๊ฐ์ง€๋œ ๋ฉ”์‹œ์ง€ ์ฐฝ

์ด ์ถœ๋ ฅ ์ฐฝ์—์„œ F4 ๋˜๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋”๋ธ” ํด๋ฆญํ•˜๋ฉด, ์†Œ์Šค ์ฝ”๋“œ์˜ ์–ด๋Š ๋ถ€๋ถ„์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ํ‘œ์‹œํ•ด์ค๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๊ฐ์ง€๋œ ๋ถ€๋ถ„์ด ํ‘œ์‹œ๋œ ๋ชจ์Šต

๊ทธ๋Ÿผ, ์ถœ๋ ฅ ์ฐฝ์— ํ‘œ์‹œ๋œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Detected memory leaks! ๋ฉ”์‹œ์ง€ ์ดํ›„์— xxx.cpp(161)์€ ํ•ด๋‹น ๊ฒฝ๋กœ์˜ ์†Œ์Šค ํŒŒ์ผ์˜ 161 ๋ผ์ธ์—์„œ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  {579}๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์ˆœ์„œ๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, 579๋ฒˆ์งธ ํ• ๋‹น๋œ ๋ถ€๋ถ„์— ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ๊ฒฌ๋๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. 0x01602760๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ์ด๊ณ , 100 bytes long์€ ๋ˆ„์ˆ˜๋œ ํฌ๊ธฐ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ MFC ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์นœ์ ˆํ•˜๊ฒŒ ์†Œ์Šค ์ฝ”๋“œ ํŒŒ์ผ๊ณผ ๋ผ์ธ๊นŒ์ง€ ์ถœ๋ ฅ๋˜์–ด ํŽธํ•˜๊ฒŒ ๋””๋ฒ„๊น…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” xxxDlg.cpp์˜ ์ƒ๋‹จ์— ์•„๋ž˜์ฒ˜๋Ÿผ ์ •์˜๊ฐ€ ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

์œ„ ์ฝ”๋“œ์˜ ์˜๋ฏธ๋Š”, Debug ๋ชจ๋“œ๋ผ๋ฉด new๋ฅผ DEBUG_NEW๋กœ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. DEBUG_NEW๋Š” afx.h์— ์•„๋ž˜์ฒ˜๋Ÿผ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

#define THIS_FILE          __FILE__
//...
#define DEBUG_NEW new(THIS_FILE, __LINE__)

C++ Console ์˜ˆ์‹œ

์ด๋ฒˆ์—๋Š” C++ Console ํ”„๋กœ์ ํŠธ์—์„œ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. main()์— ๋‹ค์Œ์ฒ˜๋Ÿผ 100byte๋ฅผ ๋™์  ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

int main()
{
	byte* buff = new byte[100];

	return 0;
}

๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ ํ›„ ์ข…๋ฃŒํ•˜๋ฉด ์ถœ๋ ฅ ์ฐฝ์— ๋ณ„๋‹ค๋ฅธ ๋ฉ”์‹œ์ง€๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์—†๋Š”๊ฒƒ ๊ฐ™์ฃ ?

๋””๋ฒ„๊ทธ ์‹คํ–‰ ๊ฒฐ๊ณผ ํ™”๋ฉด

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์—†๋Š”์ง€ ์ ๊ฒ€ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

#include "pch.h"
#include <iostream>
#include <Windows.h>

#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>

int main()
{
	byte* buff = new byte[100];

	_CrtDumpMemoryLeaks();

	return 0;
}

๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ ํ›„ ์ข…๋ฃŒํ•˜๋ฉด ๋ฉ”์‹œ์ง€ ์ฐฝ์— Detected memory leaks! ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

Memory Leak์ด ๊ฐ์ง€๋œ ๋ฉ”์‹œ์ง€ ์ฐฝ

MFC์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ์†Œ์Šค ํŒŒ์ผ๊ณผ ๋ผ์ธ ์ˆ˜๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

#include "pch.h"
#include <iostream>
#include <Windows.h>

#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>

#ifdef _DEBUG
#define new new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#endif

int main()
{
	byte* buff = new byte[100];

	_CrtDumpMemoryLeaks();
	
    return 0;
}

๋ณ€๊ฒฝ๋œ ์†Œ์Šค ์ฝ”๋“œ ์‹คํ–‰ ํ›„ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์†Œ์Šค ํŒŒ์ผ๊ณผ ๋ผ์ธ์ด ํ‘œ์‹œ๋œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฉ”์‹œ์ง€

์ด์ œ ์†Œ์Šค ํŒŒ์ผ๊ณผ ๋ผ์ธ ์ˆ˜๊ฐ€ ํ‘œ์‹œ๋˜๊ณ , F4 ๋˜๋Š” ๋”๋ธ” ํด๋ฆญ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ง€์  ํ™•์ธ์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค. MFC์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, new๋ฅผ new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )๋กœ ์น˜ํ™˜ํ•˜์—ฌ ์„ธ๋ถ€ ๋‚ด์šฉ ์ถœ๋ ฅ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ํ•œ ๊ฐ€์ง€ ๋” ์•Œ๋ ค๋“œ๋ฆด ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฉ”์‹œ์ง€์— {86}์ด ์žˆ๋Š”๋ฐ์š”. ์ด๋Š” 86๋ฒˆ์งธ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์—์„œ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. main() ์ฒซ ๋ถ€๋ถ„์— _CrtSetBreakAlloc(86)์„ ์ถ”๊ฐ€ํ•˜๋ฉด, 86๋ฒˆ์งธ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์ง€์ ์—์„œ ์‹คํ–‰์ด ์ค‘์ง€๋ฉ๋‹ˆ๋‹ค.

#include "pch.h"
#include <iostream>
#include <Windows.h>

#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>

#ifdef _DEBUG
#define new new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#endif

int main()
{
	_CrtSetBreakAlloc(86);

	byte* buff = new byte[100];

	_CrtDumpMemoryLeaks();

	return 0;
}

์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ํ™”๋ฉด

ํ˜ธ์ถœ ์Šคํƒ(Call Stack)์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜ธ์ถœ ์ˆœ์„œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ˜ธ์ถœ ์Šคํƒ ํ™”๋ฉด

์„ธ ๋ฒˆ์งธ์— Exam_MemoryLeak.exe!main() ์ค„ 22๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค. ๋”๋ธ” ํด๋ฆญํ•˜๋ฉด ์•„๋ž˜์˜ ํ™”๋ฉด์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Break๊ฐ€ ๊ฑธ๋ฆฐ ์ง€์ 

ํ•˜์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•์€ ์กฐ๊ธˆ ์• ๋งคํ•ฉ๋‹ˆ๋‹ค. MFC์—์„œ ๋™์ผํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์ˆœ์„œ๊ฐ€ ์‹คํ–‰ ๋•Œ๋งˆ๋‹ค ๋ฐ”๋€Œ์–ด ์ ์šฉ์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ C++ Console์€ ํ•ญ์ƒ ์ผ์ •ํ•˜๋”๊ตฐ์š”. ์ด ๋ถ€๋ถ„์€ ์•„์ง ์˜๋ฌธ์ด์ง€๋งŒ, ๊ตณ์ด ํ•„์š”ํ•˜์ง„ ์•Š์„ ๊ฒƒ ๊ฐ™๋„ค์š”. 

๋งˆ์ง€๋ง‰์œผ๋กœ, ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ๋ถ€๋ถ„์— _CrtDumpMemoryLeaks()๋ฅผ ๋„ฃ๋Š” ๊ฒƒ ๋Œ€์‹ , ์ฒซ ๋ถ€๋ถ„์— _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF)๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

#include "pch.h"
#include <iostream>
#include <Windows.h>

#define _CRTDBG_MAP_ALLOC
#include <cstdlib>
#include <crtdbg.h>

#ifdef _DEBUG
#define new new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#endif

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

	byte* buff = new byte[100];

	//_CrtDumpMemoryLeaks();

	return 0;
}

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ ์ฐฝ์— ์†Œ์Šค ํŒŒ์ผ๊ณผ ๋ผ์ธ ์ˆ˜๊ฐ€ ํ‘œ์‹œ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์ง€์ ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ง€๊ธˆ๊นŒ์ง€ ์„ค๋ช…ํ•œ ๊ฒƒ์„ ํ† ๋Œ€๋กœ, ์ตœ์ข…์ ์œผ๋กœ ์œ„ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•˜๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Exam_MemoryLeak.zip
0.00MB

๋ฐ˜์‘ํ˜•