programing tip

프로덕션 코드에서 NSLog ()를 사용해서는 안된다는 것이 사실입니까?

itbloger 2020. 6. 7. 10:39
반응형

프로덕션 코드에서 NSLog ()를 사용해서는 안된다는 것이 사실입니까?


나는이 사이트에서 이것을 몇 번 들었지만 이것이 사실인지 확인하고 싶었다.

내 코드 전체에 NSLog 함수 호출을 뿌릴 수있을 것으로 기대했으며 릴리스 / 배포 빌드를 빌드 할 때 Xcode / gcc가 해당 호출을 자동으로 제거합니다.

이것을 사용하지 않아야합니까? 그렇다면 숙련 된 Objective-C 프로그래머들 사이에서 가장 일반적인 대안은 무엇입니까?


전 처리기 매크로는 실제로 디버깅에 좋습니다. NSLog ()에는 아무런 문제가 없지만 더 나은 기능으로 자체 로깅 기능을 정의하는 것은 간단합니다. 여기에 내가 사용하는 것이 있는데, 여기에는 파일 이름과 줄 번호가 포함되어있어 로그 문을보다 쉽게 ​​추적 할 수 있습니다.

#define DEBUG_MODE

#ifdef DEBUG_MODE
    #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
    #define DebugLog( s, ... ) 
#endif

이 전체 문장을 자체 파일이 아닌 접두사 헤더에 넣는 것이 더 쉽다는 것을 알았습니다. 원하는 경우 DebugLog를 사용하여 일반 Objective-C 객체와 상호 작용하여보다 복잡한 로깅 시스템을 구축 할 수 있습니다. 예를 들어, 자체 로그 파일 (또는 데이터베이스)에 기록하고 런타임에 설정할 수있는 'priority'인수를 포함하는 로깅 클래스를 가질 수 있으므로 디버그 메시지는 릴리스 버전에 표시되지 않지만 오류 메시지는 ( 이 작업을 수행하면 DebugLog (), WarningLog () 등을 만들 수 있습니다.

아, #define DEBUG_MODE응용 프로그램의 다른 곳에서 재사용 할 수 있습니다. 예를 들어, 내 응용 프로그램에서 라이센스 키 확인을 비활성화하고 특정 날짜 이전의 응용 프로그램 만 실행하도록 허용하는 데 사용합니다. 이를 통해 최소한의 노력으로 시간이 제한적이고 완전한 기능을 갖춘 베타 사본을 배포 할 수 있습니다.


-prefix.pch 파일의 끝에이 3 행을 넣으십시오.

#ifndef DEBUG
  #define NSLog(...) /* suppress NSLog when in release mode */
#endif

프로젝트 DEBUG를 만들 때 기본적으로 빌드 설정에 정의되어 있으므로 프로젝트에 아무것도 정의 할 필요가 없습니다 .


NSLog 호출은 프로덕션 코드에 남겨 둘 수 있지만 실제로 예외적 인 경우 나 시스템 로그에 기록 될 정보에 대해서만 있어야합니다.

시스템 로그를 어지럽히는 응용 프로그램은 성가 시며 전문가가 아닙니다.


Marc Charbonneau의 답변 에 대해서는 언급 할 수 없으므로이 답변으로 게시 할 것입니다.

사전 컴파일 된 헤더에 매크로를 추가하는 것 외에도 Target 빌드 구성을 사용하여 정의 (또는 정의 부족)를 제어 할 수 있습니다 DEBUG_MODE.

" 디버그 "활성 구성 을 선택하면 DEBUG_MODE정의되고 매크로가 전체 NSLog정의로 확장됩니다 .

은 "선택 해제 "활성 구성하는 것은 정의하지 않습니다 DEBUG_MODENSLog카는 릴리스 빌드에서 생략된다.

단계 :

  • 대상> 정보 입수
  • 빌드 탭
  • "전 처리기 매크로"(또는 GCC_PREPROCESSOR_DEFINITIONS) 검색
  • 구성 선택 : 디버그
  • 이 수준에서 정의 편집
  • 더하다 DEBUG_MODE=1
  • 구성 선택 : 릴리스
  • 확인 DEBUG_MODE이 설정되어 있지 않습니다GCC_PREPROCESSOR_DEFINITIONS

정의에서 '='문자를 생략하면 전 처리기에서 오류가 발생합니다.

또한 매크로 정의 위에이 주석 (아래 그림 참조)을 붙여 넣어 DEBUG_MACRO정의의 출처 를 알려줍니다 .)

// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
//               = Debug:   DEBUG_MODE=1

편집 : Marc Charbonneau가 게시하고 sho주목 한 방법방법 보다 훨씬 낫습니다.

디버그 모드가 비활성화되었을 때 빈 기능을 사용하여 로깅을 비활성화하도록 제안한 답변 부분을 삭제했습니다. 자동 전 처리기 매크로 설정을 다루는 부분은 여전히 ​​관련이 있으므로 그대로 유지됩니다. Marc Charbonneau의 대답에 더 잘 맞도록 전 처리기 매크로의 이름도 편집했습니다.


Xcode에서 자동 (및 예상) 동작을 달성하려면 다음을 수행하십시오.

프로젝트 설정에서 "빌드"탭으로 이동하여 "디버그"구성을 선택하십시오. "전 처리기 매크로"섹션을 찾아 이름이 매크로를 추가하십시오 DEBUG_MODE.

...

편집 : 매크로 를 사용하여 로깅을 활성화하고 비활성화하는 Marc Charbonneau의 답변참조하십시오 DEBUG_MODE.


나는 매튜에 동의합니다. 프로덕션 코드에서 NSLog에는 아무런 문제가 없습니다. 실제로, 그것은 사용자에게 유용 할 수 있습니다. 즉, NSLog를 사용하는 유일한 이유가 디버그를 돕기 위해서라면 릴리스하기 전에 제거해야합니다.

또한이 질문을 iPhone 질문으로 태그 했으므로 NSLog는 리소스를 사용합니다. 이는 iPhone이 거의 소중하지 않은 것입니다. 있는 거 NSLogging의 당신이 만약 아무것도 귀하의 응용 프로그램에서 프로세서 시간을 빼앗아 아이폰에. 현명하게 사용하십시오.


간단한 사실은 NSLog가 느리다는 것입니다.

그런데 왜? 이 질문에 답하기 위해 NSLog가 무엇을하고 어떻게하는지 알아 봅시다.

NSLog는 정확히 무엇을합니까?

NSLog는 두 가지 작업을 수행합니다.

It writes log messages to the Apple System Logging (asl) facility. This allows log messages to show up in Console.app. It also checks to see if the application's stderr stream is going to a terminal (such as when the application is being run via Xcode). If so it writes the log message to stderr (so that it shows up in the Xcode console).

Writing to STDERR doesn't sound difficult. That can be accomplished with fprintf and the stderr file descriptor reference. But what about asl?

The best documentation I've found about ASL is a 10 part blog post from Peter Hosey: link

Without going into too much detail, the highlight (as it concerns performance) is this:

To send a log message to the ASL facility, you basically open a client connection to the ASL daemon and send the message. BUT - each thread must use a separate client connection. So, to be thread safe, every time NSLog is called it opens a new asl client connection, sends the message, and then closes the connection.

Resources could be found here & here.


As noted in other answers you can use a #define to alter whether NSLog is used or not at compile time.

However a more flexible way is to use a logging library like Cocoa Lumberjack thatallows you to change whether something is logged at runtime as well.

In your code replace NSLog by DDLogVerbose or DDLogError etc, add a #import for the macro definitions etc and setup the loggers, often in the applicationDidFinishLaunching method.

To have the same effect as NSLog the configuration code is

[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];

From a security point of view, it depends on what is being logged. If NSLog (or other loggers) is writing sensitive information, then you should remove the logger in production code.

From an auditing point of view, the auditor does not want to look at each use of NSLog to ensure its not logging sensitive information. He/she will simply tell you to remove the logger.

I work with both groups. We audit code, write the coding guides, etc. Our guide requires that logging is disabled in production code. So the internal teams know not to try it ;)

We will also reject an external app that logs in production because we don't want to accept the risk associated with accidentally leaking sensitive information. We don't care what the developer tells us. Its simply not worth our time to investigate.

And remember, we define 'sensitive', and not the developer ;)

I also perceive an app which performs lots of logging as an app ready to implode. There's a reason so much logging is performed/needed, and its usually not stability. Its right up there with 'watchdog' threads that restart hung services.

If you have never been through a Security Architecture (SecArch) review, these are the sorts of things we look at.


You shouldn't be needlessly verbose with printf or NSLog in release code. Try only doing a printf or NSLog if the app has something bad happen to it, I.E. an unrecoverable error.


Keep in mind that NSLogs can slow down the UI / main thread. It is best to remove them from release builds unless absolutely necessary.


I would highly recommend using TestFlight for logging (free). Their method will override NSLog (using a macro) and allow you to turn on/off logging to their server, Apple System log and STDERR log, for all your existing calls to NSLog. The nice thing about this is you can still review your log messages for apps deployed to testers and apps deployed in the App Store, without the logs appearing on the user's system log. The best of both worlds.

참고URL : https://stackoverflow.com/questions/300673/is-it-true-that-one-should-not-use-nslog-on-production-code

반응형