public class CustomPanel : System.Windows.Forms.Panel

{

    protected override System.Drawing.Point ScrollToControl(System.Windows.Forms.Control activeControl)

    {

        // Returning the current location prevents the panel from

        // scrolling to the active control when the panel loses and regains focus

        return this.DisplayRectangle.Location;

    }

}



http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/

'library > .NET' 카테고리의 다른 글

static 클래스 초기화 주의  (0) 2020.08.13
예외처리  (0) 2019.06.27
wcf 프로젝트 설정  (0) 2011.09.05
블로그 이미지

란마12

,

메모리 누수 체크

library/CRT 2011. 10. 27. 19:49

#define _CRTDBG_MAP_ALLOC_NEW
#include <stdlib.h>
#include <crtdbg.h>

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

void ExitHandler(){
  _CrtDumpMemoryLeaks();
}

void main(){
#ifdef _DEBUG
  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
 //_crtBreakAlloc = 129;
 //_CrtSetBreakAlloc(132);
 atexit(&ExitHandler);
#endif
}

다음과 같이 누수가 보고됐다면

Detected memory leaks!
Dumping objects ->
{994} normal block at 0x00DA55A0, 8 bytes long.
 
Data: <        > CD CD CD CD CD CD CD CD
{993} normal block at 0x00DA5558, 8 bytes long.
 
Data: <        > CD CD CD CD CD CD CD CD
{992} normal block at 0x00DA54C8, 8 bytes long.
 
Data: <        > CD CD CD CD CD CD CD CD


중괄호 안의 숫자, 예를 들어 {994} 지점에서 중단점을 설정

_crtBreakAlloc = 994; 또는 _CrtSetBreakAlloc(994);


- stl변수가 전역으로 초기화 되면 릭이 발생된 것으로 표시됨.
  가능하면 전역으로 쓰지말고 함수의 정적변수로 사용.

- vld쓰다가 최신 버전으로 교체했는데 멀티스레드에서 com사용할 때 문제가 있는 듯.

- 메인 프로세스에서 참조하고 있는 dll library내의 누수는 잡지 못함.(dll내에서 초기화시 위와 같은 체크준비를 똑같이 해야 함)




'library > CRT' 카테고리의 다른 글

CRT(C Runtime) Debugger사용방법  (0) 2014.05.14
컴파일 옵션  (0) 2013.02.22
errno  (0) 2011.01.08
유니코드를 위한 함수  (0) 2011.01.08
시간과 날짜와 관련된 라이브러리 함수들  (0) 2010.12.15
블로그 이미지

란마12

,
1. 참조

System.ServiceModel
System.ServiceModel.Discription
System.Runtime.Serialization

2. 서버

 2.1. 윈도우 서비스일경우
  - 빌드 전 이벤트
     net stop "서비스 이름"
     REM 이미 멈춰있을 경우 오류처리 무시
     IF %errorlevel%==2 exit 0
  - 빌드 후 이벤트
     REM net start "서비스 이름"
     REM 오류처리 무시
     REM IF %errorlevel%==2 exit 0
  - 서비스 설치/제거
     C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe 서비스경로/파일명
     C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u 서비스경로/파일명

3. 클라이언트

 3.1. 서비스 참조/업데이트 시 당근 해당서비스가 실행중이어야 함.
 3.2. 대량의 데이터를 받을 경우 binding객체의 MaxReceivedMessageSize, ReaderQuotas.MaxArrayLength 크길를 늘림.

4. 디버깅
 4.1. #if DEBUG
                Debugger.Launch();
       #endif

'library > .NET' 카테고리의 다른 글

static 클래스 초기화 주의  (0) 2020.08.13
예외처리  (0) 2019.06.27
Panel Resets Scroll Position after Focus is Lost and Regained  (0) 2012.10.06
블로그 이미지

란마12

,

vs2008
HKLM\Software\Microsoft\VisualStudio\8.0\NativeDE\StepOver
aaa=std\:\:.*=NoStepInto

 vs2010
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\NativeDE\StepOver]
"aaa"="std\:\:.*"

'library > STL' 카테고리의 다른 글

erase  (0) 2010.12.14
map insert 반환값  (0) 2010.09.12
copy  (0) 2010.02.09
블로그 이미지

란마12

,

errno

library/CRT 2011. 1. 8. 22:49

표준 C에서는 errno를 통해서 실패의 이유를 알 수 있다.

다음은 예제는 C에서의 에러 처리 기법이다.
int main()
{
        FILE* f = fopen("a.txt", "rt");

        if ( f == 0 )
        {
            printf("error : %d\n", errno);
            printf("%s\n", strerror(errno ));        // errno를 문자열로 바꿔준다.
            perror("FAIL");                                // fprintf( stderr, "FAIL : %s\n", strerror(errno)) 의미
        }
}
여기서 문제는 error가 전역변수 라는 것이다. 지금은 문제가 안되겠지만, 멀티스레드 환경에서는 이 변수를 공유하기 때문에
문제가 될 수 있다.
그래서 윈도우즈 환경에서는 에러정보를 스레드당 한개씩 갖고 있게된다.

윈도우즈 환경에서는 스레드를 만들때마다 구조체가 한개씩 생성된다. 이 구조체를 TEB(Thread Environment Block)라 한다.
즉, 스레드가 10개 생성되면 TEB도 10개가 생성되는 것이다.

이 TEB안에는 모든 스레드별로 다양한 정보가 있는데, 그중에 Last Error Value 정보가 있다. 이Last Error Value가 C에서의 errno역할을 한다. 스레드당 한개씩 생기기 때문에 멀티스레드 환경에서 안전하다고 할 수 있다.

이 때, Last Error Value값을 꺼내오는 함수가 바로 GetLastError()이다.

또, TEB의 전체 내용은 User Memory에 있기 때문에 우리가 접근할 수 있고, WinDBG를 사용하면 TEB의 내용도 확일할 수 있다.

ex) dt nt!_TEB

http://sungjinl2e.egloos.com/3325928


'library > CRT' 카테고리의 다른 글

컴파일 옵션  (0) 2013.02.22
메모리 누수 체크  (0) 2011.10.27
유니코드를 위한 함수  (0) 2011.01.08
시간과 날짜와 관련된 라이브러리 함수들  (0) 2010.12.15
문자열 함수들의 버퍼 체크 방법 차이  (0) 2010.11.24
블로그 이미지

란마12

,

1. 유니코드와 멀티바이트 간 변환 관련

 1.1. MultiByteToWideChar()
 1.2. WideCharToMultiByte()

 1.3. W2A, A2W


#include <atlconv.h>

char szMult[] = "멀티녀석들!!";
wchar_t szWide[] = L"유니코드닷";

USES_CONVERSION; //무조건 정의
strcpy(szMult, W2A(szWide)); // 유니코드 -> 멀티바이트 복사
_tcscpy(szWide, W2A(szMult)); // 멀티바이트 -> 유니코드 복사

 

 1.4. _bstr_t

  #include <comutil.h>

  #pragma comment (lib,"comsuppw.lib" )


  _bstr_t str(L"asdfasfd가나다라");

 

   wchar_t* pstrw = str;

   char* pstra = str;

   TCHAR* pstrt = str;


   주의: sprintf 등 함수의 가변인자로 사용할 경우 반드시 타입을 명시해 줘야한다. 

           sprintf(pstra, "%s", (LPCSTR)pstrw);


2. 문자열 변환 관련


TCHAR szBuf[5] = "a";
StringCchCat(szBuf, _countof(szBuf), "bcdefgh"); //abcd
_tcsncat(szBuf, "bcdefgh", _countof(szBuf)); //abcdefgh

StringCch*계열 함수
 - 널종료에 대해 신경쓰지 않아도 된다.
 - strlwr()함수등 지원하지 않는 함수가 많다.

결론 : StringCch*계열 함수를 쓰되 지원되지 않는 함수에 대해 _tcs*계열 함수를 쓰자.

'library > CRT' 카테고리의 다른 글

메모리 누수 체크  (0) 2011.10.27
errno  (0) 2011.01.08
시간과 날짜와 관련된 라이브러리 함수들  (0) 2010.12.15
문자열 함수들의 버퍼 체크 방법 차이  (0) 2010.11.24
코딩시 Unicode 관련 고려사항  (0) 2010.11.23
블로그 이미지

란마12

,

STL string vs CRT char

library 2011. 1. 4. 13:14

string
 - 버그 발생의 소지가 줄어듬
 - 익숙해지면 강력
 - 표준

char
 - 윈도우 API다루기 편함
 - 추가 라이브러리 필요없음
 - 성능이 더 낫다(밀리초 수준에서)


결론: string을 사용해야 맞다. 그러나 나는 가능하면 추가라이브러리 없이 사용할 수 있도록 개발하고 싶다.

'library' 카테고리의 다른 글

정규 표현식(Regular Expression)  (0) 2012.12.03
블로그 이미지

란마12

,

DllMain이 언제, 왜 호출되는지에 대하여 알아보자.

DllMain의 정의는 아래와 같다.

-------------------------- DllMain의 원형 -------------------------------

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);

----------------------------------------------------------------------

1. HINSTANCE hinstDll
   - DLL이 가상주소에 매핑되었을 때의 핸들이다. WinMain의 hInstance 와 동일한 셩격을 갖고있다.
   - IMAGE_OPTIONAL_HEADER 의 ImageBase 필드에 지정된 값이다.  보통 디폴트로 0x10000000 번지에 로드된다.

2. DWORD fdwReason
   - DllMain 이 호출한 이유를 나타낸다.
   - fdwReason 의 값으로는
     -> DLL_PROCESS_ATTACH : DLL이 프로세스의 주소 공간에 최초로 매핑됬을때

     -> DLL_PROCESS_DETACH : DLL이 프로세스의 주소 공간으로 부터 해제될 때

     -> DLL_THREAD_ATTACH : 어떤 프로세스 내에서 스레드가 생성될 때 해당 프로세스 주소공간에 매핑되어 있는 모든 DLL의 파일이미지검사하여 DLL_THREAD_ATTACH 로 호출

     -> DLL_THREAD_DETACH : 스레드 엔트리 포인트 함수로부터 리턴될때 시스템은 ExitThread를 호출한다 이때 스레드를 바로 없애지 않고 매핑되어 있는 모든 DLL의 DllMain에 DLL_THREAD_DETACH를 호출

-----------------------------------------------------------------------------------------------------------------------------------------

DllMain을 정의할 때 주의할 점이 있는데 DllMain을 호출할때 동기화를 맞추어야 한다.

예를 들어 스레드가 생성될 때 DLL_THREAD_ATTACH 를 매개 변수로 하여 DllMain이 호출된다. 이때 다른 스레드가 종료되는 상황이라면

DllMain이 동시에 두 개의 스레드에 대하여 호출되는 상황이 발생할 것앋. 이 경우 동기화 문제를 고려할 필요가 없도록 시스템이 알아서

앞에 호출된 DllMain의 실행이 끝날 때까지 DllMain의 실행을 대기시키게 된다. 이런 상황 때문에 DllMain 내에서 대기 함수(WaitForXXX 함수군들)를 호출할 때 신중을 기해야 한다.

아니 이런 상황이 발생하지 않도록 코딩해야 한다.  제프리 책 Programming Applications for Microsoft Windows 2000에 이런 상황이 발생할 수 있는 문제점에 대한 예제가 나오는데

확인해보자

------------------------------------- 데드락이 발생하는 DllMain의 예) ----------------------------------------

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID lpvReserved)
{
 HWND hThread;
 DWOIRD dwThreadld;

 switch(fdwReason)
 {
 case DLL_PROCESS_ATTACH:
 hThred = CreateThread(NULL,0,SomeFunction,NULL,0,&dwThreadld); // 스레드하나 생성
 
  WaitForSingleObject(hThread, INFINITE);  // 스레드가 끝날때 까지 DllMain 실행을 대기 시킨다.

  CloseHandle(hThread);
 break;

 case DLL_PROCESS_DETACH:
 break;

 case DLL_THREAD_ATTACH:
 break;

 case DLL_THREAD_DETACH:
 break;

 }

}

----------------------------------------------------------------------------------------------------

위 코드를 보면 Dll 로드시에 호출되는 DllMain에서 스레드를 하나 생성하였다.

이 스레드가 종료할때까지 메인 스레드를 대기하는 코드다

이 프로그램은 데드락 상태에 빠지게 되는데  메인스레드는 SomeFuction을 실행하는 스레드를 생성키기고

WaitForSingleObject 를 통해 SomeFuction 의 실행이 종료될 때까지 대기한다.

하지만 여기서 문제가 되는것은 스레드 생성시에도 DLL_THREAD_ATTACHG를 매개변수로 하여 DllMain이 호출된다는 것이다.

그리고 앞서 언급한 것처럼 이미 DLL_PROCESS_ATTACH를 매개 변수로 하여 메인 스레드에 의해 DllMain이 호출 중이기 때문에

시스템은 메인 스레드가 실행 중인 DllMain 실행이 끝날때까지 SomFunction을 실행하는 스레드를 위한

DllMain 실행을 대기시킨다. 이 상황, 즉 메인 스레드에 의한 DllMain 실행은 SomeFunction 을 실행하는 스레드가 종료되기를 기다리고 있으며

SomeFuction 을 실행할 스레드는 SomeFunction을 실행하기 전에 DllMain을 호출하기 위하여 메인 스레드에 의한 DllMain의 호출이 끝나기를 기다리고 있다.

서로가 서로를 끝나기만 기다리고 있는 것이다. 이런 실수를 범하지 않도록 DllMain정의 시에 신중을 기해야 한다.

 


블로그 이미지

란마12

,

시간과 날짜와 관련된 라이브러리 함수

구분

함수 원형과 인자

함수 설명

시간

계산

time_t time(time_t *timeptr);

1970 1 1일 자정부터 경과된 현재 시간을 초단위로 계산

시간을

문자열로

변환

char *asctime(strcut tm *time);

구조체 tm형식의 시간을 문자열로 변환

char *ctime(time_t *time);

함수 time()로부터 계산된 현재 시간을 문자열로 변환

시간을

구조체로

변환

struct tm *localtime(time_t *time);

지역 시간(local time)을 구조체 tm의 형식으로 가져오는 함수

struct tm *gmtime(time_t *time);

Greenwich Meam Time(GMT)을 구조체 tm 형식으로 가져옴

시간

차이

계산

clock_t clock(void);

clock tick으로 경과된 시간

double difftime(time_t time2, time_t time1);

두 시간의 차이를 초단위로 계산

시간

지연

void Sleep(unsigned millisecond);

인자가 지정하는 만큼의 1/1000초 단위의 시간을 지연

void delay(unsigned millisecond);

 

예제

  

#include<stdio.h>

#include<time.h>

 

int main(void)

{

    time_t now;

    time(&now);

    printf("현재날짜와시간: %s", asctime(localtime(&now)));

    printf("현재날짜와시간: %s", ctime(&now));

 

    return 0;

}

 

 

 

strcut tm은 <time.h>에 다음과 같이 정의되어 있다.

 

struct tm {

        int tm_sec;     /* (seconds)       - [0,59] */

        int tm_min;     /* (minutes)       - [0,59] */

        int tm_hour;    /* 시간(hour)        - [0,23] */

        int tm_mday;    /* 날짜(day)         - [1,31] */

        int tm_mon;     /* (month)         - [0,11] */

        int tm_year;    /* 1900년이후의연도수*/

        int tm_wday;    /* dydlf(second)     - [0,6] */

        int tm_yday;    /* 연중날짜(day)     - [0,365] */

        int tm_isdst;   /* 일광절약시간      - [0, 59] */

        };

 

예제

 

#include<stdio.h>

#include<time.h>

int main(void)

{

    time_t curr;

    struct tm *d;

    curr=time(NULL);

    d=localtime(&curr);

    printf("현재날짜\n");

    printf("%d%d%d\n", d->tm_year+1900, d->tm_mon+1, d->tm_mday);

    printf("현재시간\n");

    printf("%d%d%d\n", d->tm_hour, d->tm_min, d->tm_sec);

    return 0;

}

 

 

 

 

time과 clock의 차이

구분

함수 time

함수 clock

원형

time_t time(time_t *timer);

clock_t clock(void);

기능

절대시간 또는 달력시간(calendar time)을 계산

프로세서 시간을 계산

반환 값

1970 1 1일 자정 이후 현재까지 경과된 시간을 초(second)로 반환

프로세서 시간을 반환

 

예제 - 함수 time 사용

  

#include<stdio.h>

#include<time.h>

 

int main(void)

{

    time_t start, end;

    long i=0;

    double pst;

 

    start=time(NULL);

 

    while(i<30000000)

    {

        i++;

    }

 

    end=time(NULL);

    pst=difftime(end, start);

    printf("time: %f\n", pst);

 

    return 0;

}

/**초단위의시간을계산하는함수time()의결과는0초**/

 

예제 - 함수 clock 사용

  

#include<stdio.h>

#include<time.h>

 

int main(void)

{

    time_t start, end;

    long i=0;

    double pst;

 

    start=clock();

 

    while(i<30000000)

    {

        i++;

    }

 

    end=clock();

    pst=(double)(end-start)/CLK_TCK;

    printf("time: %f\n", pst);

 

    return 0;

}

 

 

시간을 지연시키는 함수 Sleep 예제

  

#include<stdio.h>

#include<time.h>

#include<windows.h>    //Sleep()

 

int main(void)

{

    clock_t start, end;

    double pst;

 

    start = clock();

    printf("start!\n");

    Sleep(3500);

    end = clock();

    printf("end\n");

    pst = (double)(end-start)/CLK_TCK;

    printf("경과시간: %f\n", pst);

 

    return 0;

}

 

 

 

시간을 처리하는 함수와는 다른 개념의 함수이지만 유용하게 사용할 수 있는 함수로 kbhit가 있다. 이 함수의 원형은 다음과 같이 함수의 인자가 없으며, 키보드 상의 어떤 키를 누르면 0이 아닌 값을, 누르지 않은 상태라면 0값을 반환하는 함수다. 함수 kbhit는 <conio.h>를 필요로 한다.

kbhit

함수원형

int kbhit(void);

반환 값

입력된 키가 있으면 0이 아닌 값을, 입력된 키가 없으면 0을 반환

 

프로그램 실행중에 아무키나 누르기 전까지만 프로그램을 계속 반복시키고자 한다면 반복문 while과 함께 다음과 같이 사용할 수 있다.

while(!kbhit())

{

    //반복할프로그램

}

 

예제 - 현재 시간을 연속적으로 출력(kbhit, localtime)

 

#include<stdio.h>

#include<time.h>

#include<stdlib.h>

#include<conio.h>

int main(void)

{

    time_t now;

    struct tm *d;

 

    while(!kbhit())

    {

        system("cls");

        now=time(NULL);

        d=localtime(&now);

        printf("현재날짜와시간: %s\n", asctime(d));

    }

    return 0;

}

 

 

 

날짜 수와 요일 계산

기준일(1년 1월 1일)로부터 특정일 사이의 날짜 수의 계싼 함수 total_days

long total_days(int year, int month, int day)

{

    int months[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    int i;

    long total=0L;

 

    total=(year-1)*365L+(year-1)/4-(year-1)/100+(year-1)/400;

    if(!(year%4) && year%100 || !(ytear%400))

        months[1]++;

    for(i=0;i<month-1;i++)

        total += months[i];

    total += day;

 

    return total;

}

 

특정일의 요일 계산

  

#include<stdio.h>

 

long total_days(int year, int month, int day);

 

int main(void)

{

    int year, month, day;

    char *week_day[] = {"", "", "", "", "", "", ""};

    long total;

 

    printf("특정일의요일구하는프로그램\n\n");

    printf("입력될숫자는space bar로분리하고\n");

    printf("Enter 키를누릅니다.\n");

    printf("예로2005 5 1 Enter\n");

    printf("년월일입력: ");

    scanf("%d %d %d", &year, &month, &day);

 

    total=total_days(year, month, day);

 

    printf("%s 요일입니다.\n", week_day[total%7]);

 

    return 0;

}

 

long total_days(int year, int month, int day)

{

    int months[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    int i;

    long total=0L;

 

    total=(year-1)*365L+(year-1)/4-(year-1)/100+(year-1)/400;

    if(!(year%4) && year%100 || !(year%400))

        months[1]++;

    for(i=0;i<month-1;i++)

        total += months[i];

    total += day;

 

    return total;

}

 

 

특정일 사이의 날짜 수를 계산

  

#include<stdio.h>

 

long total_days(int year, int month, int day);

 

int main(void)

{

    long total;

   

    total=total_days(2010, 7, 21) - total_days(1987, 4, 16);

 

    printf("두날짜사이의날짜수: %ld\n", total);

 

    return 0;

}

 

long total_days(int year, int month, int day)

{

    int months[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    int i;

    long total=0L;

 

    total=(year-1)*365L+(year-1)/4-(year-1)/100+(year-1)/400;

    if(!(year%4) && year%100 || !(year%400))

        months[1]++;

    for(i=0;i<month-1;i++)

        total += months[i];

    total += day;

 

    return total;

}

 

 

 


'library > CRT' 카테고리의 다른 글

errno  (0) 2011.01.08
유니코드를 위한 함수  (0) 2011.01.08
문자열 함수들의 버퍼 체크 방법 차이  (0) 2010.11.24
코딩시 Unicode 관련 고려사항  (0) 2010.11.23
디버그 시 malloc 메모리 누수 탐지  (0) 2010.07.16
블로그 이미지

란마12

,

erase

library/STL 2010. 12. 14. 19:22

STL에서 가장 짜증나는 부분이 erase부분이 아닌가 싶다. erase와 remove의 차이점을 알아야 하고 거기에 몇 개 종류별 iterator의 erase 기법을 알아야 한다. 흠... 암기하기도 그렇고...꽤나 귀찮은 것들 하나다. 그래서 찾아본 것을 정리하면 아래와 같습당...

map's iterator  erase 방법

// 1. 특정 조건에 따라 제거
map<..., ...> mp;
for(map<..., ...>::iterator i=mp.begin(); i != mp.end(); )
{
 if( {조건문} ) {
   mp.erase( i++ );   
 } else {
   ++i;    
 }
}

// 2. 전체 제거
map<..., ...> mp;
for(map<..., ...>::iterator i=mp.begin(); i != mp.end(); )
{
 mp.erase( i++ );   
}

vector's iterator  erase 방법

// 1. 특정 조건에 따라 제거
vector<...> vec;
for(vector<...>::iterator i=vec.begin(); i != vec.end(); )
{
 if( {조건문} ) {
   i = vec.erase( i );   
 } else {
   ++i;    
 }
}

// 2. 전체 제거
vector<..., ...> vec;
for(vector<..., ...>::iterator i=vec.begin(); i != vec.end(); )
{
 i = vec.erase( i );   
}

http://linkmemo.tistory.com/category/?page=6

'library > STL' 카테고리의 다른 글

STL관련 step into무시하기  (0) 2011.04.21
map insert 반환값  (0) 2010.09.12
copy  (0) 2010.02.09
블로그 이미지

란마12

,