CriticalSection : 하나의 Process에서 여러개의 Thread의 상호배제 구현
    선언 : CRITICAL_SECTION m_CrtSection;
    초기 :
    생성 : InitializeCriticalSectionAndSpinCount(&m_CrtSection, 2000);//Multi CPU를 지원 Spin Count를 추가 한다.
    진입 : EnterCriticalSection(&m_CrtSection);
    진출 : LeaveCriticalSection(&m_CrtSection);
    소멸 : DeleteCriticalSection(&m_CrtSection);

 

Mutex : 이름을 지정하여 여러개의 Process의 Thread에서도 상호배제 가능.Mutex는 동기화 대상이 오직 하나뿐일 때
    선언 : HANDLE m_hMutex;
    초기 : m_hMutex=NULL;
    생성 : m_hMutex=CreateMutex(NULL,FALSE,NULL); //OpenMutex()
    진입 : WaitForSingleObject(m_hMutex,INFINITE);
    진출 : ReleaseMutex(m_hMutex);
    소멸 : if(m_hMutex !=NULL ) CloseHandle(m_hMutex);

 

Semaphore : 여러 Process의 한가지 자원에 접근 배제.Semaphore는 동기화 대상이 하나 이상일 때 사용
    선언 : HANDLE m_hSemaphore;
    초기 : m_hSemaphore=NULL;
    생성 : m_hSemaphore= CreateSemaphore(
            NULL, // default security attributes
            3, // initial count. MAX_COUNT 10
            3, // maximum count. MAX_COUNT 10
            NULL); // unnamed semaphore

            WaitForMultipleObjects(5, &aThread[0], TRUE, INFINITE);
    진입 : dwWaitResult = WaitForSingleObject( 
            m_hSemaphore, // handle to semaphore
            0L); // zero-second time-out interval
            // Return value : 리턴값 ( dwWaitResult 에 저장되는 값 )
            // WAIT_ABANDONED 0x00000080L
            // WAIT_OBJECT_0 0X00000000L
            // WAIT_TIMEOUT 0x00000102L
            // WAIT_FAILED 0xFFFFFFFF(DWORD)
    진출 : ReleaseSemaphore(m_hSemaphore, // handle to semaphore
            1, // increase count by one
            NULL) ) // not interested in previous count

    소멸 : if(m_hSemaphore !=NULL ) CloseHandle(m_hSemaphore);

 

Event
    선언 : HANDLE m_hEvent;
    초기 : m_hEvent=NULL;
    생성 : m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); ResetEvent(m_hEvent);
    진입 : WaitForSingleObject(pDlg->m_hEvent, INFINITE);
    진출 : ResetEvent( hHandle );// 원하는 작업을 처리한다.
    소멸 : if(hHandle !=NULL ) CloseHandle(hHandle);
         

    이벤트 발생은 SetEvent(m_hEvent); //return value

        WAIT_FAILED : fail, GetLastError로 원인을 알수가 있다 이경우 logic을 빠져나간다
        WAIT_ABANDONED : 이 경우는 Event Object를 reset 하고 다시 WaitForSingleObject()를 호출한다
        WAIT_OBJECT_0 : 기다리던 Event가 signal 된 경우
        WATI_TIMEOUT : time-out 된 경우

Opencv 3.4 이후 문제점.
(제공 버전과 Source Build를 통해 Test를 진행하였다. 4.1.2, 3.8.4, 3.4.0 )

- Memory Leak이 있다.(단지 링크 순서에 의한 것이라지만-Debug상)

 

OpneCV 진영의 먹칠(??)이다 ㅡ.ㅡ;


조치 1)
Static MFC DLL로 조치
     --> cv::Mat을 사용할 때 __acrt_first_block == header
heap Error 발생.(debug에서만 발생.)
(사용 불가.)
     --> Local Project는 Debug이지만 Dll은 신뢰 하영 Release로 Link시 사용하는 Opencv C++ Class Link error 발생.
(사용 불가.)

조치 2)
모두 동적 Link로 Build 지연된 DLL로 변경. 프로그램 시작(동작 없이) 종료 시 Leak 없음.
     -->cv::Mat Class 함수 호출 IplImage 사용호 종료 시 Memory Leak 발생.

결론 현재 VS2017로 컴파일하는 3.2 버전 이상에서는
     => Memory Leak을 조치하면, __acrt_first_block == header 발생으로 C++Mat를 사용할 수 없다.
     => 다중 스레드 디버그(/MTd and /MT)에서 그나마 유연하게 동작한다.
          (__acrt_first_block == header를 발생시키는 코드도 있다.)
     => 3.2 이상 버전으로 갈수록 C++형태의 코드와 더 많은 STL사용으로 컴파일 강도가 높아지고 있는 듯하다.

 

다른 분들은 어떠실지 모르지만 현재 3.2 버전 이후에는
Memory Leak, Heap에러의 조치가 없다면, 버전업을 할 수 없을 듯하다.
- 가짜 Memory Leak은 Main S/W Debugging을 힘들게 한다.
- Heap에러는 S/W 신뢰도를 떨어뜨린다.

 

다른 의견이나 정보가 있으시면 공유 부탁드립니다.........

 

Heap Error 발생 코드. (3.4.0 이후...)

void MatTest(Mat*pdraw)
{
	Mat ProcImg = pdraw->clone();
	vector<vector<Point>> contours;
	cv::findContours(ProcImg, contours, RetrievalModes::RETR_EXTERNAL, 
    ContourApproximationModes::CHAIN_APPROX_NONE);
}
void CMatTesterDlg::OnBnClicked()
{
	TCHAR szFilter[] = 
    _T("Image (*.bmp, *.gif, *.jpg *.tif)|*.bmp;*.gif;*.jpg;*.tif|All Files(*.*)|*.*||");
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter, GetParent());
	dlg.m_ofn.lpstrInitialDir = MARK_IMG_PATH;
	if (IDOK == dlg.DoModal())
	{
		USES_CONVERSION;
		CString strPathName = dlg.GetPathName();
		Mat matLoadImg = imread(W2A(strPathName.GetBuffer(strPathName.GetLength())), 
        cv::IMREAD_COLOR);

		if (matLoadImg.empty() != true)
		{
			Mat matCh1Img;
			cvtColor(matLoadImg, matCh1Img, ColorConversionCodes::COLOR_RGB2GRAY);
			
			cv::threshold(matCh1Img, matCh1Img, 50, 255, THRESH_BINARY);
			MatTest(&matCh1Img);
			
			namedWindow("Process", WINDOW_NORMAL); // Create a window for display.
			imshow("Process", matLoadImg);
		}
	}
}

 

 

설정 상태.

'작업 > OpenCV' 카테고리의 다른 글

CvvImage 추가 3.4 까지  (0) 2021.11.09
처리시간 측정  (0) 2020.07.17
OpenCV 컴파일(3.4.0, 3.4.8, 4.1.2)  (0) 2019.11.21
OpenCV 4.x.x 사용 C++ Runtime Library Debug  (0) 2019.11.20
OpenCV Memory Leak  (0) 2019.11.20

생성 시 주의 점

 

1) Memory Leak현상.

a) 정적 라이브러리에서 MFC사용

=> 기본 OpneCV가 동적 Link DLL로 컴파일됨으로 C++ 사용 코드에서 오류 발생 시킴 비추천

https://sw-mcreator.tistory.com/15?category=816240

MFC 사용 방식 변경

b) 지연 dll등록으로 처리.(동적 오류, Memory Leak둘다 해결) 추천

DLL, Lib 위치한 폴더 지정
Lib를 종속시키고, DLL은 지연 시키다.

 

컴파일 OpneCV 3.4.0(OpneCV 4.1.2동일)

(CMake를 통한 Visual Studio 프로젝트 만들기.)

 

 

1) source Code 폴더 선택
2) 출력 폴더 선택 (VS2017 64 or 32)
3) button Configure 진행(Visual Studio의 종류와 64/32bit 선택)
4) Option 선택(검색창에서 Option 검색)
- OPENCV_EXTRA_MODULES_PATH <다운로드 폴더 선택.>opencv_contrib-3.4.0/modules
- OPENCV_ENABLE_NONFREE

- BUILD_PERF_TESTS
- BUILD_TESTS
- BUILD_JAVA
- BUILD_PACKAGE
- BUILD_opencv_world

- WITH_1394
- WITH_GSTREAMER
- WITH_LAPACK
- WITH_VTK

- CMAKE_INSTALL_PREFIX <경로 선택>
- INSTALL_C_EXAMPLES

5) button Generate 진행
6) button Open Project 진행
7) Visual Studio Debug/Release 컴파일 진행.
8) 프로젝트중 "INSTALL"프로젝트만 따로 Build 진행.
-> 위에서 선택한 결과 폴더에 결과물이 저장된다. 특히 "include"폴더 필요.

 

Local Project 만들기.(EXE, DLL)
- Opencv의 Link혹은 Process오류(에러)를 제거 하기위해.
되도록 Link 구조는 동일 하게 유지 하자.
구성 속성 ->일반 -> MFC 사용 : "공유 DLL에서 MFC 사용"
구성 속성 ->C/C++ ->코드 생성->런타임 라이브러리 :"다중 스레드 디버그 DLL(/MDd and /MT)

'작업 > OpenCV' 카테고리의 다른 글

CvvImage 추가 3.4 까지  (0) 2021.11.09
처리시간 측정  (0) 2020.07.17
OpneCV Test(4.1.2, 3.8.4, 3.4.0)  (0) 2019.11.22
OpenCV 4.x.x 사용 C++ Runtime Library Debug  (0) 2019.11.20
OpenCV Memory Leak  (0) 2019.11.20

Expression: __acrt_first_block == header

 

void MatTestVector(Mat *pProcImg)
{
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;

	cv::findContours(*pProcImg, contours, hierarchy, 
    RetrievalModes::RETR_EXTERNAL,
    ContourApproximationModes::CHAIN_APPROX_NONE);
}

 

오류 발생

분석.

- vector가 선언되고 findcontoures()가 실행 후 발생.

(Release Mode에서는 미 발생.)

 

-OpneCV 3.2.0에서 IplImage와 CvSeq사용 시 미 발생.

void MatTestVector(IplImage *pTargetImg)
{
	CvMemStorage *storage = cvCreateMemStorage();
	CvSeq *contours = nullptr;
	CvSeq *contour = nullptr;
	cvFindContours(pTargetImg, storage, &contours, sizeof(CvContour), 
    				CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0, 0));
}

 

방법.

1. Vector의 선언을 전역으로 변경.

2. Vector의 선언을 1번과 같은 방법 이지만 "static"으로 선언.(사용중)

void MatTestVector(Mat *pProcImg)
{
	static vector<vector<Point> > contours;
	static vector<Vec4i> hierarchy;

	cv::findContours(*pProcImg, contours, hierarchy, 
    				RetrievalModes::RETR_EXTERNAL, 
                    ContourApproximationModes::CHAIN_APPROX_NONE);
}

*정확한 원인과 해결 방법을 아시는 분은 댓글 부탁드립니다.

 

<참고>

STL에 객체가 선언되고, DLL 내부에서 메모리를 할당 메모리 해제 순서에 의해 발생.

==> Expression: __acrt_first_block == header

App와 DLL의 메모리 관리

* App 메모리 생성 -> DLL에서 사용 -> App에서 해지.

* App DLL 함수 호출 -> DLL안에서 메모리 생성 -> DLL안에서 사용 -> DLL 안에서 메모리 해지 -> APP의 결과 전달.

즉, 메모리를 생성한 곳에서 해지 하자.

(App에서 생성하였으면 App에서, DLL에서 생성한 것이면 DLL에서 해지 하자~~!!!)

 

Expression: __acrt_first_block == header

'작업 > OpenCV' 카테고리의 다른 글

CvvImage 추가 3.4 까지  (0) 2021.11.09
처리시간 측정  (0) 2020.07.17
OpneCV Test(4.1.2, 3.8.4, 3.4.0)  (0) 2019.11.22
OpenCV 컴파일(3.4.0, 3.4.8, 4.1.2)  (0) 2019.11.21
OpenCV Memory Leak  (0) 2019.11.20

*원인 

 실제 Memory Leak이 있는 것이 아니다.

 - MFC DLL와의 Loading 순서에 의한 것 이다.

 

*해결 방법

1. MFC DLL을 Link하도록 하여 OpneCV DLL 생성.

2. "MFC 사용"을 "공유 DLL에서 MFC사용"에서 "정적 라이브러리에서 MFC 사용"으로 변경.

3. OpenCV DLL을 Project->"속성"->"링커"->"입력"->"지연 로드된 DLL"에 등록.

 

-> 1번 시도 안함.(그냥 외부항목 포함 Build 할 때도 에러가 많아 귀찮음 시간도 걸림)

-> 2번 가장 단순하고, 적용이 쉽다. EXE가 커지긴 하여도 이식성에서도 유리.(현재 해당 방법 사용중)

-> 3번 배포용 DLL사용시 Link하여 사용. (필자는 코드에 Lib Loading을 하여 미사용.)

 

OpenCV Link후 실행->종료->Memory Leak발생 감지.

 

설정 변경 "정적 라이브러리에서 MFC 사용"

'작업 > OpenCV' 카테고리의 다른 글

CvvImage 추가 3.4 까지  (0) 2021.11.09
처리시간 측정  (0) 2020.07.17
OpneCV Test(4.1.2, 3.8.4, 3.4.0)  (0) 2019.11.22
OpenCV 컴파일(3.4.0, 3.4.8, 4.1.2)  (0) 2019.11.21
OpenCV 4.x.x 사용 C++ Runtime Library Debug  (0) 2019.11.20

*VS2017에는 Installer가 기본 제공되지 않는다.

- 대상 항목을 업데이트 하여 추가 하자.

확장 및 업데이트에서 추가 해주자.

 

 

해당 Update를 찾아 다운로드 한다.

*다운로드가 완료되면 모든 Visual Studio를 닫아 준다. 그러면 아래 설치 관리자가 실행 된다.

Installer 설치 진행
Installer 프로젝트가 추가 되었음을 확인 한다.

 

나머시 설정은 타 TiStory에 정리가 잘되어 있으니 참고 하세요.

1) MFC  Dialog Base에서 F1 Key에 의한 Main Process Holding을 막기 위함입니다.

 

  - 초기 생성되는 APP 파일(" CTestPrgramDlg.cpp, CTestProgram.cpp")

BEGIN_MESSAGE_MAP(CTestProgramApp, CWinApp)
	//ON_COMMAND(ID_HELP, &CWinApp::OnHelp)//<<====주석 처리
END_MESSAGE_MAP()

2) 기타 종료 키 감지 및 막기

BOOL CTestProgramDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
	//F1은 ON_COMMAND(ID_HELP, CWinApp::OnHelp)주석처리
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F4)  //F4 Close App...
		return TRUE;
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) //ESC키 눌렀을때 방지..
		return TRUE;
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE) //Space키 눌렀을때 방지..
		return TRUE;
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) //Enter키 눌렀을때 방지..
		return TRUE;
	return CDialogEx::PreTranslateMessage(pMsg);
}

+ Recent posts