프로가 되자.

post search result

프로그래밍와 관련된 글 23개를 찾았습니다.

  1. 2009/11/20 Android 다운로드 시 “remote end hung up unexpectedly" 오류가 발생할 때
  2. 2008/10/23 멀티 프로세서 이용하기
  3. 2008/04/09 IsDebuggerPresent() 구현하기
  4. 2007/10/22 ContinueModal() 에서 ASSERTION FAILED (1)
  5. 2007/06/30 VC DLL에서 DEF를 사용하지 않고 export 하기
  6. 2007/06/30 Use VC++ to create a DLL file and use its functions in Visual Basic 6 Programming Tips (1)
  7. 2007/06/28 프로그램 최적화 문제
  8. 2007/06/19 컴파일 시간에서의 assert() 구현
  9. 2007/06/09 php에서의 포인터
  10. 2007/05/03 학생 관리 프로그램

Android 다운로드 시 “remote end hung up unexpectedly" 오류가 발생할 때

Android platform을 repo를 이용하여 git에서 다운로드 할 때 자꾸 remote end hung up unexpectedly 라는 오류가 나면서 접속이 끊기는 경우가 있습니다.

이럴 땐 다음과 같은 방법으로 피해(?)를 최소화 할 수 있습니다:

1. repo init 하여 초기화 해 놓은 디렉토리로 이동합니다.
2. vi .repo/repo/subcmds/sync.py 를 이용하여 sync.py 파일을 편집합니다
3. _Fetch를 검색하여 다음과 같이 수정합니다.

  def _Fetch(self, projects):
    fetched = set()
    pm = Progress('Fetching projects', len(projects))
    for project in projects:
      pm.update()
      while True:
        if project.Sync_NetworkHalf():
          fetched.add(project.gitdir)
          break
        else:
          print >>sys.stderr, 'error: Cannot fetch %s' % project.name
    pm.end()
    return fetched


기존의 소스와 달라진 점이 있다면

"while True:"와 "break"를 추가한 것과 "sys.exit(1)" 을 삭제한 것이 다릅니다. 즉 그냥 소스 코드 다운로드 될 때 까지 무한 루프 돌겠다 이거죠.

크리에이티브 커먼즈 라이센스
Creative Commons License
2009/11/20 10:21 2009/11/20 10:21

top

About this post

이 글에는 트랙백이 단 1개 걸려있고, 아직 댓글이 없고, , , 태그가 달려있으며,
2009/11/20 10:21에 작성되었습니다.

멀티 프로세서 이용하기

#pragma omp section
#pragma omp parallel...
을 이용하여 멀티 프로세서를 사용함으로써 효율을 높일 수 있다. 출처 및 예제: http://deadwi.jaram.org/wiki/wikka.php?wakka=OpenMPSections/show&time=2008-09-08+17:55:15
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/10/23 09:50 2008/10/23 09:50

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , , 태그가 달려있으며,
2008/10/23 09:50에 작성되었습니다.

IsDebuggerPresent() 구현하기

Windows API 중에 IsDebuggerPresent()가 있습니다. 무엇인고 하니.. 만약 현재 프로세스에 debugger가 물려있는지의 여부(즉 내가 debugee 상태라면)를 알려줍니다. 프로그램 크랙할 때
BOOL bIsDebugger;
bIsDebugger = IsDebuggerPresent();
if(bIsDebugger == TRUE)
{
    // error!
}
와 같은 루틴을 찾아서 if문을 patch하는 방식을 주로 이용하는데요.. 이것을 직접 구현하는 방법을 알아보도록 하겠습니다. Windows에서는 Thread Environment Block라는 블록이 있습니다. 말 그대로 Thread에 관련된 환경값이 있는데요, 이 중 Thread가 속한 Process Environment Block를 구할 수 있는 field가 있습니다. TEB는 FS:[0x18]로 구하고, PEB는 아래에 나오는 구조체의 필드로부터 메모리 주소값을 얻어와서 구합니다. 왜 FS:[0x18]이냐... ring3에서는 fs레지스터가 teb를 가리키고 있게 구성 되어 있다고 합니다. 그렇다면 우선 Winternl.h에 선언되어 있는 PEB와 TEB의 구조를 보겠습니다. (VS 2003입니다) 재미있는건 PEB를 IsDebuggerPresent(), CheckRemoteDebuggerPresent() 대신 BeingDebugged 필드를 이용하여도 된다고 하네요.
//
// Instead of using the BeingDebugged field, use the Win32 APIs
//     IsDebuggerPresent, CheckRemoteDebuggerPresent
// Instead of using the SessionId field, use the Win32 APIs
//     GetCurrentProcessId and ProcessIdToSessionId
// Sample x86 assembly code that gets the SessionId (subject to change
//     between Windows releases, use the Win32 APIs to make your application
//     resilient to changes)
//     mov     eax,fs:[00000018]
//     mov     eax,[eax+0x30]
//     mov     eax,[eax+0x1d4]
//
typedef struct _PEB {
    BYTE Reserved1[2];
    BYTE BeingDebugged;
    BYTE Reserved2[229];
    PVOID Reserved3[59];
    ULONG SessionId;
} PEB, *PPEB;

//
// Instead of using the Tls fields, use the Win32 TLS APIs
//     TlsAlloc, TlsGetValue, TlsSetValue, TlsFree
//
// Instead of using the ReservedForOle field, use the COM API
//     CoGetContextToken
//
typedef struct _TEB {
    BYTE Reserved1[1952];
    PVOID Reserved2[412];
    PVOID TlsSlots[64];
    BYTE Reserved3[8];
    PVOID Reserved4[26];
    PVOID ReservedForOle;  // Windows 2000 only
    PVOID Reserved5[4];
    PVOID TlsExpansionSlots;
} TEB;
typedef TEB *PTEB;
역시 MS......... PEB와 TEB의 구조를 다 Reserved로 바꿔놓았네요. 아래는 reserved를 없애고 실제 데이터가 의미하는 바를 나타낸 구조체 입니다.
typedef struct _CLIENT_ID
{
	HANDLE UniqueProcess;
	HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef struct _RTL_USER_PROCESS_PARAMETERS
{
	BYTE Reserved1[16];
	PVOID Reserved2[10];
	UNICODE_STRING ImagePathName;
	UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

typedef struct _PEB_LDR_DATA
{
	BYTE Reserved1[8];
	PVOID Reserved2[3];
	LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _PEB_FREE_BLOCK
{
	_PEB_FREE_BLOCK *Next;
	ULONG Size;
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;

typedef void (* PPEBLOCKROUTINE)(PVOID PebLock);
typedef void **PPVOID;


typedef struct _PEB {
	BOOLEAN InheritedAddressSpace;
	BOOLEAN ReadImageFileExecOptions;
	BOOLEAN BeingDebugged;
	BOOLEAN Spare;
	HANDLE Mutant;
	PVOID ImageBaseAddress;
	PPEB_LDR_DATA LoaderData;
	PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
	PVOID SubSystemData;
	PVOID ProcessHeap;
	PVOID FastPebLock;
	PPEBLOCKROUTINE FastPebLockRoutine;
	PPEBLOCKROUTINE FastPebUnlockRoutine;
	ULONG EnvironmentUpdateCount;
	PPVOID KernelCallbackTable;
	PVOID EventLogSection;
	PVOID EventLog;
	PPEB_FREE_BLOCK FreeList;
	ULONG TlsExpansionCounter;
	PVOID TlsBitmap;
	ULONG TlsBitmapBits[0x2];
	PVOID ReadOnlySharedMemoryBase;
	PVOID ReadOnlySharedMemoryHeap;
	PPVOID ReadOnlyStaticServerData;
	PVOID AnsiCodePageData;
	PVOID OemCodePageData;
	PVOID UnicodeCaseTableData;
	ULONG NumberOfProcessors;
	ULONG NtGlobalFlag;
	BYTE Spare2[0x4];
	LARGE_INTEGER CriticalSectionTimeout;
	ULONG HeapSegmentReserve;
	ULONG HeapSegmentCommit;
	ULONG HeapDeCommitTotalFreeThreshold;
	ULONG HeapDeCommitFreeBlockThreshold;
	ULONG NumberOfHeaps;
	ULONG MaximumNumberOfHeaps;
	PPVOID *ProcessHeaps;
	PVOID GdiSharedHandleTable;
	PVOID ProcessStarterHelper;
	PVOID GdiDCAttributeList;
	PVOID LoaderLock;
	ULONG OSMajorVersion;
	ULONG OSMinorVersion;
	ULONG OSBuildNumber;
	ULONG OSPlatformId;
	ULONG ImageSubSystem;
	ULONG ImageSubSystemMajorVersion;
	ULONG ImageSubSystemMinorVersion;
	ULONG GdiHandleBuffer[0x22];
	ULONG PostProcessInitRoutine;
	ULONG TlsExpansionBitmap;
	BYTE TlsExpansionBitmapBits[0x80];
	ULONG SessionId;
} PEB, *PPEB;

typedef struct _TEB
{
	NT_TIB Tib;
	PVOID EnvironmentPointer;
	CLIENT_ID Cid;
	PVOID ActiveRpcInfo;
	PVOID ThreadLocalStoragePointer;
	PPEB Peb;
	ULONG LastErrorValue;
	ULONG CountOfOwnedCriticalSections;
	PVOID CsrClientThread;
	PVOID Win32ThreadInfo;
	ULONG Win32ClientInfo[0x1F];
	PVOID WOW32Reserved;
	ULONG CurrentLocale;
	ULONG FpSoftwareStatusRegister;
	PVOID SystemReserved1[0x36];
	PVOID Spare1;
	ULONG ExceptionCode;
	ULONG SpareBytes1[0x28];
	PVOID SystemReserved2[0xA];
	ULONG GdiRgn;
	ULONG GdiPen;
	ULONG GdiBrush;
	CLIENT_ID RealClientId;
	PVOID GdiCachedProcessHandle;
	ULONG GdiClientPID;
	ULONG GdiClientTID;
	PVOID GdiThreadLocaleInfo;
	PVOID UserReserved[5];
	PVOID GlDispatchTable[0x118];
	ULONG GlReserved1[0x1A];
	PVOID GlReserved2;
	PVOID GlSectionInfo;
	PVOID GlSection;
	PVOID GlTable;
	PVOID GlCurrentRC;
	PVOID GlContext;
	NTSTATUS LastStatusValue;
	UNICODE_STRING StaticUnicodeString;
	WCHAR StaticUnicodeBuffer[0x105];
	PVOID DeallocationStack;
	PVOID TlsSlots[0x40];
	LIST_ENTRY TlsLinks;
	PVOID Vdm;
	PVOID ReservedForNtRpc;
	PVOID DbgSsReserved[0x2];
	ULONG HardErrorDisabled;
	PVOID Instrumentation[0x10];
	PVOID WinSockData;
	ULONG GdiBatchCount;
	ULONG Spare2;
	ULONG Spare3;
	ULONG Spare4;
	PVOID ReservedForOle;
	ULONG WaitingOnLoaderLock;
	PVOID StackCommit;
	PVOID StackCommitMax;
	PVOID StackReserved;
} TEB, *PTEB;
필드들이 참 많죠; 이 중 Winternl.h에 등록되어 있는 것도 있다고 합니다만, platform sdk를 업그레이드 안해서인지 VS 2003에는 구조체들이 없더라구요. 어쨌건간에.. FS:[0x18]에 가보면 진짜로(?) TEB가 저장되어 있습니다. VC에서 TEB를 구하기 위해서는 다음과 같이 작성합니다
DWORD dwTEBAddress;

__asm
{
	push eax
	mov eax, fs:[0x18]
	mov dwTEBAddress, eax
	pop eax
}
이게 뭔말인지 모르신다면..
HANDLE hThread;
BOOL bRet;
DWORD dwTEBAddress;
CONTEXT context;
LDT_ENTRY des;

hThread = GetCurrentThread();

// segment 정보만 얻어옴
context.ContextFlags = CONTEXT_SEGMENTS;

bRet = GetThreadContext(hThread, &context);
if(bRet == FALSE)
{
	// 오류 처리
}

// FS descriptor entry계산
bRet = GetThreadSelectorEntry(hThread, context.SegFs, &des);

dwTEBAddress = ((des.HighWord.Bytes.BaseHi << 8 | des.HighWord.Bytes.BaseMid) << 16 | des.BaseLow);
요렇게 구하셔도 됩니다. 이렇게 구하셨다면.. 이제 TEB에서 PEB를 구해야 합니다.
TEB *pTEB;
PEB *pPEB;
BOOL bIsDebugger;

pTEB = (TEB *)dwTEBAddress;
pPEB = pTEB->Peb;

bIsDebugger = pPEB->BeingDebugged;
이제 bIsDebugger를 확인 하면 땡입니다. 위와 같이 하는게 귀찮으시다(?) 하면.. PEB의 offset을 직접 계산하셔도 됩니다. 즉..
BOOL bIsDebugger;

bIsDebugger = (char *)*((void **)((char *)dwTEBAddress + 0x30)) + 0x02;
에 접근 하셔도 됩니다. 이걸 이용해서 함수로 만들어 보자면..
DWORD __declspec(naked) MyIsDebuggerPresent()
{
	__asm
	{
		// ecx 백업
		push ecx
		// TEB 주소 계산
		mov eax, fs:[0x18]
		// PEB 주소 계산
		mov ecx, dword ptr [eax + 0x30]
		// PEB->BeingDebugged 값을 가져오기 전 eax 초기화
		xor eax, eax
		// PEB->BeingDebugged 필드 값을 al에 저장(al = 8bit)
		mov al, byte ptr [ecx + 0x02]
		// ecx 복구
		pop ecx
		// // return eax
		retn
	}
}
와 같이 되겠습니다. C 버전으로 보길 원하신다면..
DWORD MyIsDebuggerPresent()
{
	HANDLE hThread;
	BOOL bRet;
	DWORD dwTEBAddress;
	CONTEXT context;
	LDT_ENTRY des;
	TEB *pTEB;
	PEB *pPEB;

	hThread = GetCurrentThread();

	// segment 정보만 얻어옴
	context.ContextFlags = CONTEXT_SEGMENTS;

	bRet = GetThreadContext(hThread, &context);

	if(bRet == FALSE)
	{
		return 0;
	}

	// FS descriptor entry계산
	bRet = GetThreadSelectorEntry(hThread, context.SegFs, &des);

	dwTEBAddress = ((des.HighWord.Bytes.BaseHi << 8 | des.HighWord.Bytes.BaseMid) << 16 | des.BaseLow);

	pTEB = (TEB *)dwTEBAddress;
	pPEB = pTEB->Peb;

	return pPEB->BeingDebugged;
}
이게 되겠네요.
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/09 22:15 2008/04/09 22:15

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , , , , , 태그가 달려있으며,
2008/04/09 22:15에 작성되었습니다.

ContinueModal() 에서 ASSERTION FAILED

MFC로 코딩하다.. KillFocus 부분에서 OnCancel() 나 OnOK()를 호출하였는데, 이게 왠일! 오류가 나는게 아닌가? 그것도 내가 짠 코드가 아닌 wincore.cpp 에서..

// wincore.cpp 4530 line
    // acquire and dispatch messages until the modal state is done for (;;)
    {
        ASSERT(ContinueModal()); // 여기서 오류가!
        // phase1: check to see if we can do idle work
        while (bIdle && !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
        {
            ASSERT(ContinueModal()); // show the dialog when the message queue goes idle
            if (bShowIdle)
            {
                ShowWindow(SW_SHOWNORMAL);
                UpdateWindow();
                bShowIdle = FALSE;
            }
...


위에 주석으로 표시된 부분에서 ASSERT 오류가 났다. 왜? 왜? 왜? 그렇다면 ContinueModal()로 들어가보자.

// wincore.cpp 4599 line
BOOL CWnd::ContinueModal()
{
    return m_nFlags & WF_CONTINUEMODAL;
}


결과적으로 WF_CONTINUEMODAL flag가 켜져 있지 않으면 오류가 난다 이거다. 이것도 문제가 생길때가 있고 안생길때가 있어서 사람을 미치게 만드는데.. 그럼 뭐가 문제일까? 결론부터 말하자면 dialog가 없어졌는데 (= 핸들이 해제되었는데) 메시지를 보내서 문제가 되는것이며, 이는 WM_KILLFOCUS같은 메시지가 처리되면서 dialog가 해제되어 발생하는 문제로 파악되어 진다. (SendMessage는 메시지를 바로 처리하는 함수이기 때문에) 해결책은? WM_KILLFOCUS안에서 PostMessage로 Dialog를 종료한다. 그러면 WM_KILLFOCUS가 모두 호출 된 뒤 message queue에서 종료메시지를 받게 된다. 즉,

void CYourDlg::OnKillfocus()
{
    // OnClose나 OnOK 대신 PostMessage(WM_CLOSE);
}


와 같이 코딩하면 된다.
크리에이티브 커먼즈 라이센스
Creative Commons License
2007/10/22 11:27 2007/10/22 11:27

top

About this post

이 글에는 아직 트랙백이 없고, 댓글이 단 1개 달려있고, , , , , , 태그가 달려있으며,
2007/10/22 11:27에 작성되었습니다.

VC DLL에서 DEF를 사용하지 않고 export 하기

def파일에서 export 한 뒤, 함수 이름을 써주어야 하는데 이렇게 하기 귀찮다면 코드 안에서 pragma 키워드를 이용할 수 있다.

다음과 같이 에 export 시킬 함수를 적고 에 function의 mangled-name을 적어주면된다.
여기서 mangled-name을 구하는 방법이 있는데 보통은

1. 함수 이름 앞에 _를 붙인다.
2. 함수 이름 뒤에 @를 붙인다.
3. @뒤에 함수 인자의 총 바이트 수를 추가한다.

예를들어

int a(int arg1);


와 같은 구문이 있다면 a함수의 mangled-name은 _a@4 가 된다. 마찬가지로,

int a(int arg1, int arg2);


와 같은 함수는 _a@8이 된다.
이와 같이 <export>과 <function>을 결정한 뒤 다음과 같이 export 하면된다.

#pragma comment(linker, "/export:<export>=<function>")


P.S. 이 작업을 한 뒤 기존에 export하던 함수의 __declspec(dllexport)부분을 삭제해야 여기서 export한 함수 이름만 표시되는것을 볼 수 있다
크리에이티브 커먼즈 라이센스
Creative Commons License
2007/06/30 11:53 2007/06/30 11:53

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , , 태그가 달려있으며,
2007/06/30 11:53에 작성되었습니다.

Use VC++ to create a DLL file and use its functions in Visual Basic 6 Programming Tips

VC에서 만든 DLL을 VB에서 사용할 때 애먹고 있으신 분들을 위해..
참고로, 굳이 프로젝트 세팅에서 __stdcall 방식으로 바꿀 필요는 없다.
이렇게 하면 c 코드를 작성하는 모든 부분의 데이터를 이상하게 처리해야될지 모르므로 -ㅅ-;;
각 함수마다 __stdcall을 이용하면되는데..

예를 들면

int __stdcall a() {}


와 같이 함수 선언부에 __stdcall를 붙이면 이 함수만 __stdcall 규약을 따르게 될 수 있다.

P.S. 보통 Windows API들이 __stdcall을 따른다. 그 이유는, Windows에서 제공하는 API들은 VC, VB, Delphi 등등의 프로그램에서 사용되어야 하므로 표준 규약인 __stdcall을 지키는것이며, 그래서 VC에서 Windows API들이 선언된 것을 보면 WINAPI 라고 된 것을 볼 수 있다. 이 WINAPI는 PASCAL 형이며, PASCAL은 _pascal 의 별칭이다. (wtypes.h에 define 되어 있으며, pascal과 stdcall방식은 서로 같다. pascal방식은 caller가 stack을 삭제하는 것이다.) 이렇게 함으로써, 우리는 쥐도새도모르게(?) Windows에서 제공하는 API를 __stdcall이라는 키워드 없이 이용할 수 있는것이다.

아래는 돌아다니다가 주워온 자료이다.





http://www.vb-helper.com/howto_vcc_dll.html

Title Use VC++ to create a DLL file and use its functions in Visual Basic 6
Description

               
This example shows how to use VC++ to create a DLL file and use its functions in Visual Basic 6.
Keywords VC++, VCC, DLL, C++
Categories Software Engineering


I have found 2 methods to do this. The first makes the VC++ easier and the Visual Basic messier. The second makes the VC++ harder and the Visual Basic easier.

Method 1: Easy VC++, Hard VB

VC++: Invoke New\Projects\Win32 Dynamic-Link Library. Enter the directory where you want the VC++ project and the project name (MyFuncsProject in the example).

VC++: Invoke New\Files\C++ Source File. Check the Add To Project box. Enter the file name (MyFuncs.cpp in the example).

VC++: Enter the function's source code. Use __declspec (note the two underscores) to export the function's symbol. Use 'extern "C"' to minimize name mangling by VC++.

// Define DllExport to declare exported symbols.
#define DllExport __declspec( dllexport )

// Prototype the function.
// Use 'extern "C"' to minimize name mangling.
extern "C" DllExport long MyCFunc(long x);

// Define the function.
extern "C" DllExport long MyCFunc(long x)
{
	return x * x;
}


VC++: Set project options using Project\Settings. On the C/C++ tab, select the Code Generation category. Then change Calling Convention to __stdcall.

VC++: Select Build\Set Active Configuration. Select the Release configuration. Repeat step 4 to make the options apply to the release configuration in addition to the debug configuration. Use Build\Set Active Configuration to reselect the debug configuration if desired.

VC++: Build the project (press F7 or use the Build menu). This creates the DLL file.

VB: In your Visual Basic program, declare the DLL function using the DLL file's full path name. The function's name in the DLL file has been slightly mangled by VC++. The name is an underscore, followed by the name you gave it, followed by "@", followed by the number of bytes in the function's argument list. In this example the name is _MyCFunc@4 because the function takes one 4 byte argument (a long integer).

Private Declare Function MyCFunc Lib "C:\VBHelper\VcDll\Method1\Release\MyFuncsProject.dll" Alias "_MyCFunc@4" (ByVal x As Long) As Long

Private Sub Command1_Click()
	Dim x As Long
	Dim y As Long

	x = CInt(Text1.Text)
	y = MyCFunc(x)
	Label1.Caption = Str$(y)
End Sub


*** HINT: To quickly determine the mangled name of the function, find the DLL file in Windows Explorer. Right click on the file and select the "Quick View" command. This presents an editor showing information about the DLL. Page down 2 or 3 pages and you will find a list of exported symbols available in the DLL. One of these will be the mangled function name.


VB: Run the program.


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


Method 2, Hard VC++, Easy VB
Steps 1 through 5 are the same as in Method 1.


VC++: New\Text File. Check the Add To Project box. Enter the file name. Give it a .DEF extension (MyFuncs.def in the example).

VC++: Enter definition file information that tells VC++ to export the function with the mangled name using the name you want it to have. The following code makes the exported name MyCFunc equivalent to _MyCFunc@4.

EXPORTS
MyCFunc=_MyCFunc@4


VC++: Build the project (press F7 or use the Build menu). This creates the DLL file.
*** HINT: Use Quick View to verify the exported names. Find the DLL file in Windows Explorer. Right click on the file and select the "Quick View" command. Page down 2 or 3 pages and you will find a list of exported symbols available in the DLL. This includes both the mangled name and the name you specified in the .DEF file.


VB: In your Visual Basic program, declare the DLL function using the DLL file's full path name. Use the name you placed in the .DEF file not the mangled name.

Private Declare Function MyCFunc Lib "C:\VBHelper\VcDll\Method2\Release\MyFuncsProject.dll" (ByVal x As Long) As Long

Private Sub Command1_Click()
	Dim x As Long
	Dim y As Long

	x = CInt(Text1.Text)
	y = MyCFunc(x)
	Label1.Caption = Str$(y)
End Sub

크리에이티브 커먼즈 라이센스
Creative Commons License
2007/06/30 11:34 2007/06/30 11:34

top

About this post

이 글에는 아직 트랙백이 없고, 댓글이 단 1개 달려있고, , , , , , , 태그가 달려있으며,
2007/06/30 11:34에 작성되었습니다.

프로그램 최적화 문제

인터넷에 돌아다니다가 최적화 문제 하나를 보았다.
다음 두 함수(method1, method2)중 어느 함수가 더 빠를까?

#include <WINDOWS.H>
#include <STDIO.H>
#define ARRAY_SIZE 8192

BYTE array[ARRAY_SIZE][ARRAY_SIZE];

void method1()
{
    int x;
    int y;
    BYTE temp;

    for(y = 0; y < ARRAY_SIZE; y++)
    {
        for(x = 0; x < ARRAY_SIZE; x++)
        {
            temp = array[x][y];
        }
    }
}

void method2()
{
    int x;
    int y;
    BYTE temp;

    for(x = 0; x < ARRAY_SIZE; x++)
    {
        for(y = 0; y < ARRAY_SIZE; y++)
        {
            temp = array[x][y];
        }
    }
}

int main()
{
    DWORD dwTick;

    dwTick = GetTickCount();
    method1();
    printf("method1: %d\n", GetTickCount() - dwTick);

    dwTick = GetTickCount();
    method2();
    printf("method2: %d\n", GetTickCount() - dwTick);

    return 0;
}


정답은 method2.
메모리를 읽을때 sequencial access와 random access의 차이.
크리에이티브 커먼즈 라이센스
Creative Commons License
2007/06/28 15:17 2007/06/28 15:17

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , 태그가 달려있으며,
2007/06/28 15:17에 작성되었습니다.

컴파일 시간에서의 assert() 구현

일반적으로 우리가 사용하는 assert()는 runtime에서 사용할 수 있다.
UPX 소스를 분석하던 중 독특한 define이 눈에 들어왔는데 그것은..

COMPILE_TIME_ASSERT(sizeof(pe_header_t) == 248)


와 같은 구문이었다.

딱 봤을때 신기하다는 생각이 들지 않는가?
compile하는 시점에서 assertion을 수행한다는 것 자체가 신기할 따름이었다.
그래서 그 define부분을 보고 분석 한 결과..

#define COMPILE_ASSERT(x)        switch(0) case 1: case !(x): break;
#define COMPILE_ASSERT2(x)        typedef int __acc_cta_t[1-!(x)];


와 같은 define문을 간추려 내었다.
(UPX에서는 각 컴파일러의 버전에 맞게 되어 있지만 여기서는 생략한다)
즉, x를 조건식으로 본 뒤 switch에서 동일한 값의 case가 있을때 오류나는 원리를 이용하여 조건을 검사하는 것이다.

두번째는, 배열의 첨자는 0이 될 수 없다는 오류 메시지를 출력하는 컴파일러를 위해 있는 구문이며, 배열의 크기가 1-!(x), 즉 참일 경우에는 1-0 이 되지만 거짓일 경우에는 1-1이 되서, 결국 배열의 첨자가 0이라는 오류를 출력하게 하는 구문이다.
참고로 typedef는 여러번 겹쳐도 되기 때문에 문제가 되질 않는다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2007/06/19 21:24 2007/06/19 21:24

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , , 태그가 달려있으며,
2007/06/19 21:24에 작성되었습니다.

php에서의 포인터

c와 php에서 포인터는 비슷하다.
하지만 가끔 헷갈리는 경우가 있는데..
조심해야되는 경우가 있다.
c처럼 생각하고 포인터를 썼다가는 큰일이 날지도 모른다는 생각에 정리해둔다.
(고수들은 이미 다 알고 있는 사실일지도 모르지만 -ㅅ- 나같이 삽질하는 초보들을 위해 정리한다)

int *p;
int a;

a = 10;

p = &a;
*p = 5;


을 php코드로 짜면 다음과 같이 될 것이다.

$a = 10;
$p = &$a;
$p = 5;


하지만 다음은 어떨까?

int *p;
int *p2;
int a;

a = 10;

p = &a;
p2 = p;
*p2 = 5;


c에서는 a가 5로 바뀐다.

php에서는..

$a = 10;
$p = &$a;
$p2 = $p;
$p2 = 5;


라고 하면?
c로 따지면 $p는 int*이지만, $p2는 int가 된다.
즉, $p2 = $p 하는 순간 p2 = *p; 와같은 식이 되어버리고 만다는것.
이걸을 방지하기 위해 $p2가 포인터 변수라는것을 알려주기 위해 다음과 같이 바꾼다.

$a = 10;
$p = &$a;
$p2 = &$p;
$p2 = 5;


$p앞에 &를 붙이면 $p2가 포인터 변수라는것을 알려주기 때문에 원하는 결과를 얻을 수 있다.

함수의 경우, 인자를 보내는쪽(?)이나 받는쪽에서 &를 붙이게 되면 자연스럽게 둘중 하나가 포인터 같이 사용될 수 있다.
예를들어

$a = 2;

myf(&$a);

function myf($b)
{
	$b = 10;
}


와 같은 코드가 있다면 $a의 값이 10으로 바뀐다. 반대로

$a = 2;

myf($a);

function myf(&$b)
{
	$b = 10;
}


라고 해도 마찬가지의 결과를 얻을 수 있다. 물론 둘다 &라고 해도 정상적으로 된다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2007/06/09 11:53 2007/06/09 11:53

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , 태그가 달려있으며,
2007/06/09 11:53에 작성되었습니다.

학생 관리 프로그램

학부 시절 만든 프로그램이다.

후배가 만들어달라고 해서 만들어준거 같은데 (기억이 가물가물)

지금 보니 코드가 "생각보다" 깔끔하다.

내가 옛날에 저런걸 만들었었다니..ㄷㄷㄷ

else if와 주석 다는 스타일이 좀 달라지긴 했다.

view..

크리에이티브 커먼즈 라이센스
Creative Commons License
2007/05/03 23:09 2007/05/03 23:09

top

About this post

이 글에는 아직 트랙백이 없고, 아직 댓글이 없고, , , 태그가 달려있으며,
2007/05/03 23:09에 작성되었습니다.

◀ recent : [1] : [2] : [3] : previous ▶

blog information

프로가 되자.
BLOG main image
빗소리를 먹는 사람.
RSS 2.0Tattertools
최근 글 최근 댓글 최근 트랙백
태그 구름사이트 링크