Altruistic Programmer's Blog (KR)

이타주의 프로그래머의 블로그

Archive for the ‘프로그래밍’ Category

Base SDK와 Deployment Target의 의미

without comments

꼼꼼하게 공부하고 싶은 분은 SDK Compatibility Guide를 보시라.
(http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/cross_development)

Weak Link란?

  • 링크할 때 라이브러리에 심볼(변수, 함수, 클래스 등)이 없어도 에러가 나지 않는다.
  • 앱이 로딩될 때 심볼이 없어도 에러가 나지 않는다.
  • 그래서 런타임에 심볼이 있는지 확인하고 써야한다.

Strong Link란?

  • 링크할때나 로딩할때 심볼이 없으면 에러가 난다.

Base SDK 버전이란?

  • 내 앱이 사용할 제일 높은 SDK(혹은 OS) 버전
  • 이 버전보다 높은 버전에 새로 생긴 API는 쓸 수 없다. 

Deployment Target 버전이란?

  • 내 앱이 사용할 제일 낮은 SDK (혹은 OS) 버전
  • 이 버전보다 높은 버전의 SDK에 있는 API는 Weak Link가 된다.
  • 이 버전과 같거나 낮은 버전의 SDK에 있는 API는 Strong Link가 된다.

그래서 어떻게 쓸까?

  • 내 앱이 지원할 OS의 최저, 최고 버전을 정한다.
  • Base SDK에 최고 버전을 설정한다.
  • Deployment Target에 최저 버전을 설정한다.
  • Weak Link가 되는 심볼에 대해서는 런타임에 존재하는지 확인한 다음에 써야한다.
  • Strong Link가 되는 심볼은 컴파일 타임에 에러가 발생한다.

주의 사항

  • 베이스 클래스가 존재하지 않는 경우 자식 클래스도 존재하지 않는 것으로 간주한다.
  • 클래스 인터페이스에 정의한 델리게이트가 존재하지 않는 경우 앱 실행시에 런타임 에러가 난다.

  • 특정 OS 버전에서 발생할 수 있는 문제점을 컴파일 에러로 발생시키려면 Base SDK를 해당 OS 버전으로 낮춰서 빌드해보면 된다.

Written by muscly

April 29th, 2011 at 9:09 pm

Posted in 프로그래밍

Objective-C 2.0에서 프라이빗 프로퍼티 정의하기

without comments

클래스의 헤더에 프로퍼티를 숨기고 싶은 경우에는 클래스 익스텐션을 사용할 수 있다.

// A.h
@interface A : NSObject {

}
-(void)setXXX:(int)i;
-(int)xxx;
@end

// A.m
#import "A.h"
@interface A()
@property int m; // HERE
@end

@implementation A
@synthesize m; // AND HERE
-(void)setXXX:(int)i {
self.m = i;
}
-(int)xxx {
return self.m;
}
@end

카테고리보다 클래스 익스텐션이 좋은 이유는

  1. 프로퍼티를 정의할 수 있다
  2. 메소드를 선언만하고 구현하지 않으면 에러가 난다.

Written by muscly

April 29th, 2011 at 8:17 pm

Posted in 프로그래밍

오브젝트 파일의 CPU 아키텍쳐 확인하기

without comments

오픈소스 라이브러리를 빌드에서 XCode에서 링크하려고 하면 아키텍쳐가 맞지 않는다고 에러가 날 때가 있다. 아래와 같이 하면 .a 파일 안의 .o 파일들이 어떤 CPU 아키텍쳐를 대상으로 빌드되었는지 확인할 수 있다.

otool -hv libxxxx.a

분명히 잘 빌드한 것 같은데 링크가 안되서 봤더니 x86_64라고 나온다. 강제로 -arch i386 을 넣고 빌드하니 시뮬레이터용으로 링크가 잘 된다.

참고로, 위에서 v 옵션을 빼면 cputype과 cpusubtype이 숫자로 나오는데, /usr/include/mach/machine.h 를 보면 그 숫자들의 의미를 확인할 수 있다. (그냥 v 옵션 넣고 쓰면 됨…)

Written by muscly

March 31st, 2011 at 8:20 pm

Posted in 프로그래밍

플래시 소켓과 보안 샌드박스

with 2 comments

문제상황

C++ 서버에 플래시 클라이언트를 연결시켰는데 난데없이 패킷이 날라온다. 내용을 보니 "<policy-file-request/>"라는 문자열이다. 소스코드 건든 적도 없는데 갑자기 이런다. -_-;;

Security Sandbox

플래시처럼 웹에서 돌아가는 녀석들은 보안을 위해서 특정 기능을 막는다. 샌드박스라는 개념을 만들어서, 그 샌드박스안에서 플래시가 돌아가게 만든다. 샌드박스의 종류에 따라서는 파일 시스템에 접근할 수 없고, 소켓을 사용할 수도 없다. 자세한 것은 아래 링크에서.

http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000350.html

샌드박스를 확인해보니 잘 돌아갈때는 local-trusted 샌드박스 였는데, 지금은 local-with-networking 샌드박스다. 결국 샌드박스에 변경이 생겨서 동작에 변화가 생긴 것이다.

Cross-domain Policy File

플래시의 버전에 따라서 조금씩 다른데, 플래시에서 로우 소켓을 사용해서 서버에 접속하기 위해서는 동일한 서버에 동일한 방식으로 접속을 해서 시큐러티 폴리시 파일을 받아와야한다. 이 파일에는 플래시가 돌아가는 도메인에서 서버가 돌아가는 도메인으로 소켓 연결을 해도 좋은지 허락하는 내용이 들어있다. 허락을 안할 수도 있고. 자세한 스팩은 아래.

http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html

실제 서비스라면 서버에 연결해서 폴리시 파일을 받아서 확인을 거친 후에, 동일한 서버에 다른 포트로 연결하는 패턴이 필요하다. 물론, 나는 로컬에서 테스트만 할 목적이었으므로 폴리시 파일을 받아오는 단계는 생략했었고, local-trusted 샌드박스라면 문제없이 잘 동작한다.

The User Flash Player Trust Directory

문제는 소스코드를 한 줄도 안건드렸는데 왜 샌드박스가 바뀌었을까 하는 것. 결론은 swf 파일이 어떻게 빌드되었는냐의 문제가 아니라 swf 파일이 어디 있느냐가 핵심이다. 컴퓨터의 파일시스템의 어딘가에 믿을만한 swf 파일이 있는 디렉토리가 등록되어 있다. 자세한 것은 아래.

http://livedocs.adobe.com/flex/3/html/help.html?content=05B_Security_03.html#140756

예전에 FlashDevelop을 사용할 때는 FlashDevelop이 자동으로 swf가 생기는 디렉토리를 등록해주었던 것. 이번에 빌드 자동화를 위해서 Flex SDK를 직접 사용하도록 바꾸고 swf가 생기는 디렉토리도 바꿨기 때문에 샌드박스가 변경되었던 것이다.

해결책

swf 파일이 있는 디렉토리를 믿을만한 디렉토리로서 등록한다.

Written by muscly

April 22nd, 2010 at 1:45 pm

pdb를 공부해서 LNK4099 LNK4204를 해결하다

with 2 comments

여러가지 서드파티 라이브러리중에 유독 구글의 프로토콜버퍼만 LNK4099 LNK4204 경고를 무수하게 쏟아내고 있어서 pdb에 대해서 공부를 해봤다. 평소에 궁금해하던 vc90.pdb 파일의 정체를 알게 되어서 기쁘다.

2가지 종류의 pdb

pdb파일은 아래의 두 가지 종류가 존재한다.

  • 컴파일러가 생성하는 pdb
    • /Z7, /Zi, /ZI 등의 컴파일 옵션으로 임베딩 여부와 정보의 양을 결정
    • /Fd 컴파일 옵션으로 pdb 파일이 생성될 경로를 지정
    • VC2008이 지정하는 기본패스는 $(IntDir)\vc90.pdb
    • .obj 파일에 pdb 파일의 경로를 보관한다.
  • 링커가 생성하는 pdb
    • /DEBUB 옵션으로 생성여부 결정
    • /PDB 옵션으로 pdb 파일이 생성될 경로를 지정
    • VC2008이 지정하는 기본패스는 $(TargetDir)$(TargetName).pdb
    • .exe나 .dll 파일에 pdb 파일의 경로를 보관한다.

정적 라이브러리의 pdb

정적 라이브러리는 .obj 파일의 모음으로 볼 수 있으므로 vc90.pdb가 정적 라이브러리의 pdb 파일이 된다. 즉, .lib 파일을 배포할 때는 vc90.pdb도 함께 배포해야 한다.

/Z7은 디버깅 심볼 관련 옵션이기는 하지만 pdb랑은 상관없고 CodeView 포멧의 디버깅 심볼을 .obj에 임베딩시키는 옵션이다. 정적 라이브러리라면 .lib에 임베딩되는 것이고 별도의 .pdb 파일은 생성되지 않는다. 

정적 라이브러리에 기록된 pdb 파일의 경로 읽기

LNK4099나 LNK4204 경고가 났을때 정말로 pdb 파일이 없는지 확인하기 위해서 이 방법을 사용할 수 있다. 단계를 요약해보면

  1. .lib 파일로부터 .obj 파일을 추출한다
    • lib /extract:myobj.obj mylib.lib
  2. .obj 파일에 기록된 .pdb 파일의 경로를 확인한다
    • dumpbin /section:.debug$T /rawdata myobj.obj

주의할 것은 myobj.obj는 보통 ./Debug/myobj.obj처럼 된다는 것. lib 파일을 메모장등에서 열어보면 확인할 수 있다.

LNK4099, LNK4204의 원인은?

정말로 vc90.pdb가 없거나 vc90.pdb는 있는데 그 안에 디버그 정보가 없다는 것. 이번 경우에는 프로토콜버퍼의 3가지 프로젝트가 똑같은 곳에다 vc90.pdb를 생성하는 바람에 파일이 덮어써졌다. 그래서 파일은 있지만 디버그 정보가 없는 경우에 해당한다.

구글의 C++ 테스트 프레임웍의 경우처럼 intermidiate directory(기본은 debug, release)에 프로젝트 이름을 다시 추가하는 방식으로 설정을 바꿔주면 깔끔하게 해결할 수 있다.

  • Output Directory : $(ConfigurationName)
  • Intermediate Directory : $(OutDir)\$(ProjectName)  

교훈

이 날 배운 교훈은 역시나 워닝 메시지는 친절하지 않다는 것이다. 유저인터랙션 분야에서 사용자가 어떻게 제품을 사용하는지 비디오로 녹화해서 연구하는 것과 같은 사용성 분석을 VC개발팀이 하고 있는지 궁금하다.

LNK4099의 에러메시지는 아래와 같은 포멧이다.

libprotobufd.lib(common.obj) : warning LNK4099: PDB 'vc90.pdb' was not found with 'c:\xxx\protobuf-2.2.0\vsprojects\Debug\libprotobufd.lib' or 'c:\yyy\bin\vc90.pdb';linking object as if no debug info

우선 실제로 vc90.pdb 파일이 존재하는 경로는 에러메시지에 나오지 않는다. .lib를 분석해보면 vc90.pdb의 파일 경로는 아주 온전하게 저장되어 있지만, 에러메시지에 나오지 않을 뿐이다.

c:\yyy\bin\은 라이브러리를 링크하는 exe 파일이 생성되는 위치다. 거기서 vc90.pdb를 찾고 있다는 얘기다.

그러고는 vc90.pdb 파일을 찾을 수 없다고 한다. -_-;;

링크

http://www.debuginfo.com/articles/gendebuginfo.html 
좀 옛날 것이지만 디버그 심볼에 대해서 자세하고 친절하게 설명해준 훌륭한 글


Written by muscly

April 18th, 2010 at 4:36 pm