728x90

개발을 하다보니 Enum의 Item을 문자열로 가져오고 싶어질 때가 있었다.

 

그래서 여기저기 찾아보니 다음과 같은 방법이 있었다.

 

#define ENUM_STR_A(x)     (#x)

#define ENUM_STR_W(x)    (L#x)

https://github.com/Neargye/magic_enum

 

GitHub - Neargye/magic_enum: Static reflection for enums (to string, from string, iteration) for modern C++, work with any enum

Static reflection for enums (to string, from string, iteration) for modern C++, work with any enum type without any macro or boilerplate code - GitHub - Neargye/magic_enum: Static reflection for en...

github.com

 

only header 라이브러리 이므로 그냥 사용하면 된다.

728x90
728x90

pIcmpSendEcho() 중에 Stop Debuging 시 Blue Screen이 발생한다.


이것은 나만 발생하는 현상이 아니었다.


https://social.msdn.microsoft.com/Forums/vstudio/en-US/c0d616a2-a1ea-43fb-831c-b1f51a957639/icmpsendecho-blue-screen?forum=vclanguage



위 사이트에서 NIC Driver를 다시 설치하면 된다고 했지만, 다시 설치를 해본 결과 동일한 증상이 발생하였다.



이것은 pIcmpSendEcho() 내부에서 무언가의 작업을 하는 도중에 Stop Debuging 을 하면 잘못된 메모리를 참조하면서 Blue Screen이 발생하는 것 같은데, 계속 Blue Screen을 띄우다간 작업 PC에 문제가 생길 것 같아서 더 깊게는 테스트를 해보지 못했다.




CPing 으로 알려져있는 이 방법은 우선 사용을 자제하는 것이 좋을 것 같다.


왜냐하면 아래의 링크를 보면, 굉장히 예전에 만들어진거라 충돌이 발생하는 것 같다.


https://siderite.blogspot.com/2015/07/getting-blue-screen-of-death-when.html




만약 Ping을 이용하여 다른 컴퓨터의 상태를 확인하고 싶다면, 


http://grandstayner.tistory.com/entry/Network-Ping%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%97%B0%EA%B2%B0-%EC%83%81%ED%83%9C-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0



그냥 이것을 사용하도록 하자.

728x90
728x90

Case 1


아래와 같이 Func() 내부에서 Pointer를 잘못 썻을 경우 std::thread::join() 에서 return을 안하고


Dead Lock에 걸려있는 현상이 존재한다. (std::thread의 버그인지 vs2013의 버그인지는 잘모르겠다...)




만약 join()에서 Dead Lock이 발생한다면, Pointer를 잘못 썻을 가능성을 한번 생각해보자.





Case 2



두번 째의 경우는 std::thread::join()을 하는 시점에 main() 가 없는 시점이다.


예를 들어서 Singleton Pattern 내부에서 std::thread 를 생성하고 사용한 이후 std::thread를 명시적으로 종료하지 않고, 


Singleton 의 소멸자에서 std::thread::join() 을 호출했다면, Process 의 종료 시점이어서 std::thread::join() 가 반환하고 돌아 갈 곳이 없어진 것이다.


그렇기 때문에 main() 가 없어지기 전에 명시적으로 std::thread::join() 을 호출하여 std::thread 를 종료시켜주자.


728x90
728x90

이것은 ICMP를 이용하는 방식이 아니라 그냥 system() 명령을 이용하여 간단하게 만든 것이다.


아래에 있는 소스 코드를 받아서 바로 사용하면 된다.


사용 방법은 다음과 같다.





CPingTest.cpp


CPingTest.h



p.s : 이것은 Window 에서 개발한 소스입니다...





728x90

'Basic Programming > Network' 카테고리의 다른 글

Network - Wake On Lan Magic Packet 전송  (2) 2017.08.30
728x90

Visual Studio 2013 이전 컴파일러에서 작성된 멀티바이트 문자 집합 스타일의 프로젝트를 Visual Studio 2013에서 불러와 변환 후 컴파일을 하면 다음과 같은 에러 메세지가 발생하게 된다.



error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.com/fwlink/p/?LinkId=286820 for more information.    C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets





VS 2013부터 멀티바이트문자집합용 MFC 라이브러리가 포함되지 않은 채 나오기 때문에 위와 같은 에러가 발생하는 것이다. 


쉽게 말하면, 유니코드를 사용하여 개발하라는 것이다.





하지만, MS에서 제공하는 "Visual Studio 2013용 멀티바이트 MFC 라이브러리" 를 설치하면 이 문제가 해결된다.


이것은 임시 방편이라고 생각하자.



다운로드 링크 : https://www.microsoft.com/ko-kr/download/confirmation.aspx?id=40770

728x90
728x90

이번에는 원하는 GameObject에 붙어있는 한개 이상의 Script에 구현되어있는 메소드를 호출하는 방법에 대해 이야기 해보겠습니다. 이 방법을 사용하면 해당 GameObject에 실행하고자 하는 메소드를 가진 스크립트가 컴포넌트로 존재하는지 아닌지를 크게 신경쓰지 않고도 호출하는 것이 가능합니다.

public void SendMessage(string methodName, object value = null,
SendMessageOptions options = SendMessageOptions.RequireReceiver);

SendMessage 함수는 현재 스크립트가 실행중인 GameObject에 붙어있는 모든 MonoBehaviour 스크립트의 원하는 함수를 호출해 줍니다.










하나의 GameObject에 두개의 스크립트를 붙여보았습니다. 그리고 ExampleClass1에서는 SendMessage를 사용하여 ExampleClass2에 있는 메소드를 호출해 보겠습니다.





















SendMessage를 호출할때는 파라미터를 가지고 있더라도 수신하는 메소드는 파라미터를 받지 않음으로써 넘어올 파라미터를 무시할 수 있습니다. 다음의 코드는 문제 없이 ApplyDamage() 메소드가 호출됩니다.





SendMessage는 .Net 리플렉션을 통하여 구현됩니다. 때문에 처음 찾게 되는 같은 이름을 가진 메소드를 실행하게 되며 만약 메소드 오버로딩이 되어있는 상태라면 정상적으로 동작하지 않게 됩니다.







public void SendMessageUpwards(string methodName, object value = null,
SendMessageOptions options = SendMessageOptions.RequireReceiver);

이번에는 SendMessageUpwards 메소드에 대해 알아보겠습니다. 기본적으로 SendMessage 와 동일하게 동작하지만 자신(GameObject)를 포함하여 부모 GameObject까지 메시지를 전달합니다.




위의 스크린샷과 같이 두개의 GameObject를 부모 자식 형태로 배치를 해보았습니다. 스크립트는 다음과 같이 부여하였습니다.













public void BroadcastMessage(string methodName, object parameter = null,
SendMessageOptions options = SendMessageOptions.RequireReceiver);

이번에는 위에서 설명한 SendMessageUpwards와 반대로 동작하는 메소드입니다. BroadcastMessage를 통해 메소드를 호출하게 되면 자기 자신의 GameObject를 포함하여 그의 모든 자식 객체들에게 메시지가 전달됩니다.

이번에는 부모 GameObject에서 BroadcastMessage를 실행해 보겠습니다.











BroadcastMessage 역시 마찬가지로 비활성화되어있는 GameObject는 메시지를 받을 수 없다거나 오버로딩에 정상적으로 대응 할 수 없다는 특징은 같습니다.

SendMessageOptions 은 무엇인가?

위에서 설명한 모든 메소드들의 3번째 인자로 SendMessageOptions 가 있습니다. enum 타입이며 다음과 같은 두가지 타입을 선택할 수 있습니다.

  • RequireReceiver : SendMessage에 대응할 수 있는 수신자가 반드시 있어야 합니다.
  • DontRequireReceiver : SendMessage에 대응할 수 있는 수신자가 없어도 괜찮습니다.

3번째 파라미터를 지정하지 않아도 기본 값은 RequireReceiver이며 이는 한번 메시지 호출이 발생하면 누군가는 그것을 받아서 처리를 해주어야 한다는것을 의미합니다. 만약에 대응되는 메소드가 존재하지 않는다면 오류가 발생하게 됩니다.




하지만 DontRequireReceiver 는 아무도 처리하지 않아도 문제가 되지 않습니다. Optional한 처리를 하는 경우 쓸만한 옵션일 것 같습니다.


출처 : http://theeye.pe.kr/archives/2742

728x90

'Game Programming > Unity' 카테고리의 다른 글

Unity - Mono vs IL2CPP  (0) 2024.02.26
Unity - OSVR 연동하기  (0) 2017.05.29
Unity - 단축키  (0) 2017.05.24
Unity - Logitech Extream 3D Pro 키 세팅  (0) 2017.05.23
Unity - 캐릭터 점프하기  (0) 2017.05.22
728x90

어셈블리언어에는 특정 코드 위치로 바로 이동하기 위해서 goto 키워드를 많이 사용한다.
C언어에서도 goto 키워드가 존재하지만 절차식의 C 프로그래밍을 배우면서
흐름을 깨기 때문에 사용하지 않기를 권장한다.

유닉스를 만들기 위해 개발한 언어가 C인데, 정작 유닉스 & 리눅스 코드에서는
goto 키워들 상당 부분에서 발견할 수 있다.
간단히 말해서 엉키지 않게 제대로만 쓰면 error 처리하는 용도로 편리하게 이용할 수 있다.
다시 말하면 함수의 알고리즘의 흐름 상에서 다수의 error 검출을 해서 주로 공통적인 error 처리를 하는 경우,
함수의 끝에 error를 위한 특정 코드를 추가하고 Label을 설정해서 goto 키워드를 이용하는 방식이다.

이러한 goto 대신 비슷하게 사용할 수 있는 방식이 do while을 이용하는 것이다.

do{
  if (err)
      break;
}while(0);
error_handling_code

위와 같은 방식으로 while() 안에 조건을 '0'으로 하여 한 번만 실행되게 하고,
블록 안에서 error가 발생한 경우에만 블록을 빠져나오게 하여 while 이후의 코드를 실행하게 하는 것이다.

본인이 생각컨대 goto 키워드를 굳이 써서 다른 기능을 구현하자면,
다수의 Error에 대해서 그 처리가 공통적이지 않은 경우 여러 개의 Label과
해당 Label로 이동하게 하는 goto 키워드를 써서 구현하는 것이다.
이 경우 절차식 처리에서 상당히 벗어나는 어셈블리언어식 코드가 되는데
엉키지 않도록 주의해서 사용해야 할 것이다.

쓸데 없는 얘기를 많이 한 것 같은데,
결론적으로 goto 키워드를 통한 error 처리 대신에 do while(0)을 쓸 수 있다는 것을 알아두자는 것이다. ^^;


출처 : http://neodelicious.tistory.com/46



goto문에 대한 논의 : https://kldp.org/node/40440

728x90
728x90

리눅스 커널 소스를 살펴보다가 헤더쪽의 매크로에서 “do { … } while(0)” 와 같은 것이 많이 쓰인 것을 보았다.
당연히 { … } 이 한번만 실행되고 끝나는 건데, 왜 이렇게 했을까 궁금해서 찾아보았다.

정리하자면,

1. 빈 문장(“;”)은 컴파일러에서 Warning 을 발생시키므로 이를 방지!
2. 지역변수를 할당할 수 있는 Basic block 을 쓸 수 있다.
3. 조건문에서 복잡한 문장을 사용할 수 있다. 예를 들면 다음과 같은 코드가 있다고 했을 때,

#define FOO(x) \
        printf(“arg is %s\n”, x); \
        do_something_useful(x);


다음과 같이 이 매크로를 사용한다면,

if (blah == 2)
        FOO(blah);


이렇게 해석되어서 쓰여진다.

if (blah == 2)
        printf(“arg is %s\n”, blah);
        do_something_useful(blah);;


뭐가 문제냐고? do_something_useful(blah); 는 조건에 관계없이 수행된다. 이는 원하는 결과가 아니다. 하지만 do { … } while(0) 를 쓴다면 다음과 같이 해석될 것이다.

if (blah == 2)
        do {
                printf(“arg is %s\n”, blah);
                do_something_useful(blah);
        } while (0);


정확히 원하는 결과를 얻을 수 있다.

4. 3번과 같은 경우에 다음과 같이 사용할 수도 있지 않냐고 생각할 수 있다.

#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }


그러나 다음과 같은 경우에는 원하는데로 동작하지 않는다.

if (x > y)
        exch(x,y);          // Branch 1
else  
        do_something();     // Branch 2


왜냐하면 다음과 같이 해석되기 때문이다.

if (x > y) {                // Single-branch if-statement!!!
        int tmp;            // The one and only branch consists
        tmp = x;            // of the block.
        x = y;
        y = tmp;
}
;                           // empty statement
else                        // ERROR!!! “parse error before else”
        do_something();


do { … } while(0) 를 사용하면 다음과 같이 해석되어 원하는 의도대로 정확히 쓸 수 있다.

if (x > y)
        do {
                int tmp;
                tmp = x;
                x = y;
                y = tmp;
        } while(0);
else
        do_something();


5. gcc에서는 Statements and Declarations in Expressions 확장을 사용할 수 있다. 이는 위에서 본 do-while-0 Block 대신 쓸 수 있다.



출처 : http://blog.dasomoli.org/220/

728x90

+ Recent posts