Programing/C/C++2015. 12. 29. 10:34

xml을 파싱하다 한글이 제대로 나오지 않아서 조금 찾아보니

xml의 포멧은 UTF-8인데 ANSI로 바로 사용하려고 해서 제대로 나오지 않고 있었습니다

따라서 UTF-8을 ANSI로 변환해야 하는데 아래 코드로 변환이 가능합니다

리눅스의 경우에는 하나의 함수만 사용하면 된다고 하는데 윈도우에서는 아래 2가지 함수를 사용해야 합니다

MultiByteToWideChar, WideCharToMultiByte를 사용해야 하며


변환 순서는 CHAR *(UTF-8) --> WCHAR *(UTF-8) --> CHAR *(ANSI)의 순서로 해야 합니다

자세한 내용은 아래 코드를 확인 바랍니다



Posted by ratiel
Programing/C/C++2015. 9. 14. 23:08

RegCreateKeyEx 또는 RegOpenKeyEx 사용시 samDesired의 접근 권한에 KEY_WOW64_64KEY를 '|' 연산으로 반드시 추가해야 한다


대표적으로 윈도우 설치 시간을 구할 때

'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallDate'에 실제 값이 들어 있는데 wow64 프로세스에서 접근 권한에 KEY_WOW64_64KEY를 주지 않고 RegOpenKeyEx를 호출했을 때


'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallDate'의 값을 구하려고 하면 'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\InstallDate'의 값을 구하게 된다. 해당 위치의 값은 0임


참고 사이트 : http://www.juce.com/forum/topic/registry-dword-and-binary-set/get

Posted by ratiel
Programing/C/C++2015. 9. 8. 11:20

논리 드라이브 문자로 물리 드라이브 번호를 구하는 코드.


자세한 내용은 코드의 주석 참조



Posted by ratiel
Programing/C/C++2015. 7. 22. 18:39

하드 디스크의 RPM을 구하기 위해선 우선 물리적 하드에 접근해야 합니다

물리적 하드로의 접근은 '\\\\.\\PhysicalDrive[x]'를 경로로 하여 CreateFile을 하면 오픈할 수 있으며


'\\\\.\\PhysicalDrive[x]'에서 [x] 부분은 원하는 하드의 숫자 인덱스를 넣으면 됩니다


그리고 커널에 ATA IDENTIFY DEVICE command를 요청해야 하는데 그때 사용하는 구조체와 define은 다음과 같습니다



우리가 주목할 변수는 

ATAIDENTIFYDEVICEQUERY::header::AtaFlags

ATAIDENTIFYDEVICEQUERY::header::CurrentTaskFile[6]

ATAIDENTIFYDEVICEQUERY::data[217]


이 3개 입니다. 자세한 내용은 위 define 선언과 아래 실제 사용 코드를 보면 어떻게 써야 되는지 이해할 수 있으실 겁니다

DeviceIoControl이 성공했을 때 ATAIDENTIFYDEVICEQUERY::data[217] 위치에 RPM 값이 들어오는데

SSD의 경우 RPM 값이 1로 리턴되게 됩니다

(반드시 1이 리턴되는지는 확인하지 못했으나, 현재까지 테스트해본 SSD는 모두 1을 리턴하였습니다)


해당 데이터가 1인지 아닌지를 확인하여 HDD / SDD 구분을 하면 되며

HDD라면 1이 아닌 WORD형의 RPM값이 리턴되므로, 해당 값을 사용하면 됩니다


이제 구조체에 값을 넣고 DeviceIoConrtol 함수를 호출하면 되는데요, 해당 하는 전체 코드는 다음과 같습니다

임의로 PhysicalDrive의 인덱스는 0으로 하였는데요, 원하는 물리 드라이브에 맞추어 변경하면 됩니다



Posted by ratiel
Programing/C/C++2011. 11. 2. 19:38
헤더파일에 static 변수를 선언하고 다른 cpp 파일에서 사용할 경우 각각 다른 객체로 인식됩니다

그림으로 예를 들면

statictest.h 파일에 저렇게 statis DWORD test[2] = (0, }으로 선언을 하고 

publictest.cpp, publictest2.cpp 두개의 파일에 include를 해보고 디버깅을 해봤습니다



두 그림을 비교하면 주소 자체가 틀린것을 확인할 수 있습니다

각각의 cpp마다 다른 객체로 인식이 되어서 주소가 틀려지게 되는데요

이렇기 때문에 특정 부분에서 동적으로 값을 넣어서 프로그램 전역적으로 공유할려고 하면 문제가 됩니다

프로그램 전역적으로 동일한 값을 공유할 목적이라면 특정 cpp 파일에 전역으로 변수를 선언하고

사용할곳에서 extern 키워드를 사용하는것이 좋을듯 합니다


 
Posted by ratiel
Programing/C/C++2010. 4. 20. 03:30

현재 하나의 프로세스로 여러 계정이 서버에 다중접속하는 프로그램을 제작하고 있는데

overlapped 입/출력 방식을 사용해서 send와 recv를 사용하는걸로 만들고 있는중

구동 방식은 send는 1초 간격으로 모든 계정이 서버에 동일한 패킷을 보내고, 서버에서 보내는 패킷은 recv하는데(에코는 아님. 서버는 서버대로 패킷을 보내고 있음)

recv할때 단순히 돌려버리면 WSAENOBUFS 에러가 나버리네

그래서 recv도 전체 계정이 1초의 인터벌을 두면서 recv하는 방식으로 하니까 에러없이 동작중

흠.... 디버그를 해보니 최초 1초정도는 아무런 패킷도 안와서 ERROR_IO_PENDING만 리턴하는데
그것만으로도 자원을 갉아먹나?

근데 그렇다고 동기화 방식으로 바꾸게 되면 스레드로 동작하고 있어서 recv나 send에서 블럭되어버리면 난감

뭔가 해결방법이 없나 더 봐야겠다
Posted by ratiel
Programing/C/C++2010. 3. 30. 14:22

===========================================================================

 

class critical_section

{

private:

       CRITICAL_SECTION sec;

       int count;

public:

       int enter() {EnterCriticalSection(&sec);return ++count;}

       int leave() {int rv = --count;LeaveCriticalSection(&sec);return rv;}

       int get_lock_count() {return count;}

       int get_lock_count_check() {enter();return leave();}

       inline void assert_locked() { ASSERT(get_lock_count_check()>0); }

       inline void assert_not_locked() { ASSERT(get_lock_count_check()==0); }

       critical_section() {InitializeCriticalSection(&sec);count=0;}

       ~critical_section() {DeleteCriticalSection(&sec);}

#ifdef CRITICAL_SECTION_HAVE_TRYENTER

       bool try_enter() {return !!TryEnterCriticalSection(&sec);}

#endif

};

 

class c_insync

{

private:

       critical_section * ptr;

public:

       c_insync(critical_section * p) {ptr=p;ptr->enter();}

       c_insync(critical_section & p) {ptr=&p;ptr->enter();}

       ~c_insync() {ptr->leave();}

};

 

#define insync(X) c_insync blah____sync(X)

 

 

=============================================================

 

사용하고자 하는 클래스 에서

 

아래와 같이 선언하고, 멤버중 Set/Get 메서드에서 매크로만 호출하면 됨.

 

 

 

///  예제)

 

class aa

{

      int a;

     void SetA(int n) { insync(m_sync); a=n; }

     int GetA() { insync(m_sync); return a; }

 

      critical_section m_sync;

};


InitializeCriticalSectionAndSpinCount 도 고려할것

출처 : 데브피아
Posted by ratiel
Programing/C/C++2010. 2. 23. 15:53
보통 전체 메모리를 초기화 시킬때
ZeroMemory(this, sizeof(*this)) 이용해서 전체 초기화를 시키는 방법을 자주 이용하는데요
구조체에 변수로 std::string이 들어가 있는 상태에서 위의 방법으로 초기화를 시키면
나중에 프로그램 종료시 메모리 누수가 납니다
메모리를 살펴보니
string을 생성시 메모리에 이미 값이 들어가 있는데 그것을 0으로 바꿔버리니까 문제가 발생하는것 같습니다(정확하게는 모르겠으나 아마 나중에 해제를 위한 값이 들어있는것 같음. 메모리 릭이 나는거 보면 말이죠)

해결 방법은 간단한데
구조체 변수 선언시 string들을 맨 앞에 두고
string 다음의 주소부터 string 전체 갯수의 사이즈를 뺀만큼 초기화를 시켜주면 해결됩니다
코드로 예를 들자면

struct Test
{
     std::string test_string_1;
     std::string test_string_2;
     std::string test_string_3;
     int test_int;
     ..................(필요한 변수를 더 넣는다)
     Test() //! 생성자
     {
          ZeroMemory(&test_int, (sizeof(*this) - (sizeof(std::string) * 3)));
          ..................(기타 필요한 작업)
     }
};

처음 설정된 변수부터 메모리가 할당되므로
test_int의 주소부터 전체 사이즈에서 string 3개분량의 size를 뺀 값만큼 초기화를 시켜줍니다
그러면 string을 제외한 나머지 변수들의 초기화가 완료
전체 사이즈에서 빼주는 size의 양은 string의 갯수에 따라서 조정해주세요
Posted by ratiel
Programing/C/C++2009. 12. 4. 14:37
#include<stdio.h>
#include<windows.h>

int main(int argc, char **argv)
{
     LARGE_INTEGER liCounter1, liCounter2, liFrequency;

     //! 1초당 증가되는 카운트 수를 구한다
     QueryPerformanceFrequency(&liFrequency);

     //! 코드 수행 전 카운트 저장

     QueryPerformanceCounter(&liCounter1);

     //! 시간을 측정할 코드를 여기에 넣는다

     //! 코드 수행 후 카운트 저장
     QueryPerformanceCounter(&liCounter2);

     //! 수행 시간 계산값 출력

     printf
("수행 시간 = %f 초\n", (double)(liCounter2.QuadPart - liCounter1.QuadPart) /          (double)liFrequency.QuadPart);

     return
0;
}
Posted by ratiel
Programing/C/C++2009. 11. 24. 19:56
자신이 제작한 라이브러리나 DLL이 아닌 다른 라이브러리나 DLL에서 동작하는 스레드를 강제적으로 종료시키고 싶을때 사용하면 됩니다

자기 자신의 프로세스가 아닌 다른 프로세스도 가능합니다만

그러기 위해서는 원하는 프로세스의 ID를 알아내야 합니다

코드가 저거보다는 좀 더 길어지겠죠^^

#include<TlHelp32.h> //! l가 I(아이)인지 l(엘)인지 헷갈림.. ToolHelp32Lib를 사용하므로 l(엘)으로 적어둠

//! 여기서는 종료시킬 스레드의 id를 모른다는 가정하에 코드를 작성합니다
//! 알고 있다면 그냥 OpenThread로 스레드 핸들을 얻어와서 종료시키면 되겠죠 ^^
//! 반드시 종료시킬 스레드를 제외한 모든 스레드의 id를 알고 있어야 합니다(메인 스레드 포함)
//! 여기서는 종료시키지 않을 스레드ID를 임의적으로 threadID_1, threadID_2로 지칭합니다
.....(중략)
DWORD id = GetCurrentProcessId(); //! 자기 자신의 프로세스 id를 얻어온다
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

CreateToolhelp32SnapShot() 함수를 사용하실 때 한가지 주의점은, 종료시키고 싶은 스레드가 동작 후에 호출해야 제대로 종료시키고 싶은 스레드의 ID가 나옵니다.
스레드 동작 이전에 호출해 버리면 아무리 뒤져도 종료하고픈 스레드 ID는 나오지 않습니다
이거때문에 한참을 삽질했네요;;
이 부분때문에 다른 프로세스의 스레드중 원하는 어떤 임의의 스레드를 강제 종료시키는건 어려울 것 같습니다.
그 스레드가 언제 동작할지 모르니까요 :D

THREADENTRY32 th32;
th32.dwSize = sizeof(th32); //! 이 부분을 빼먹으면 스레드 정보가 저장되지 않음
Thread32First(hSnapShot, &th32); //! 첫번째 스레드 정보 불러옴
while(1)
{
     Sleep(1);
     if (!Thread32Next(hSnapShot, &th32)) //! 전체 프로세스의 마지막 스레드까지 도달했을경우
     {
          Thread32First(hSnapShot, &th32); //! 전체 프로세스의 첫번째 스레드의 값을 넣는다
     }
     
     if (th32.th32OwnerProcessID == id) //! th32의 프로세스ID와 자신의 프로세스ID가 동일하다면
     {
          if (th32.th32ThreadID != threadID_1 && th32.th32ThreadID != threadID_2)
          {
               //! OpenThread로 스레드의 핸들을 얻어온다
               HANDLE hExitThread = OpenThread(THREAD_ALL_ACCESS, false, th32.th32ThreadID);
               TerminateThread(hExitThread, NULL); //! 스레드 종료
               CloseHandle(hExitThread);
               break;
          }
     }
}

TerminateThread는 안좋지만.. 스레드 내부에 종료 루틴이 없는 이상 별 수 없군요
Posted by ratiel