Xcode 附加到进程不显示 NSLog [英] Xcode attach to process doesn't display NSLog

查看:43
本文介绍了Xcode 附加到进程不显示 NSLog的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始使用 Apple Watch.我在

<小时>

Apple 在 技术说明 TN2239 中确认(至少对于 GDB):iOS 调试魔法.

<块引用>

控制台输出

许多程序,甚至许多系统框架,打印调试发送到 stderr 的消息.此输出的目的地最终是由程序控制:它可以将 stderr 重定向到任何它选择的目的地.但是,在大多数情况下,程序不会重定向标准错误,所以输出到默认目的地由程序从其启动环境继承.这是通常是以下之一:

  • 如果您启动一个 GUI 应用程序,因为它会被普通用户启动用户,系统将打印在 stderr 上的任何消息重定向到系统日志.您可以使用所描述的技术查看这些消息早些时候.
  • 如果你在 Xcode 中运行一个程序,你可以看到它的Xcode 的调试器控制台窗口中的 stderr 输出(选择 Console运行菜单中的菜单项以查看此窗口).

附加到运行程序(使用 Xcode 的附加到进程菜单,或附加GDB 中的命令)不会自动将程序的 stderr 连接到您的 GDB 窗口.您可以使用此技巧在 GDB 中执行此操作在附加后查看标准输出和标准错误"部分中描述技术说明 TN2030,GDB for MacsBug 退伍军人".

提到的 TN2030 在他们的服务器上不再可用 (镜像).它展示了如何将 stdout 和 stderr 重定向到 Xcode 控制台.但是,由于 shell tty 不是 LLDB 的有效命令,因此它不会有太大帮助.但也许有一种不同的方式来访问 tty Xcodes 控制台使用,所以我附上了那个 TN 的重要部分.

<块引用>

附加后看到stdout和stderr

如果您将 GDB 附加到进程(而不是启动进程从 GDB 内部),您将看不到任何过程打印到标准输出或标准错误.Finder 启动的程序通常将 stdout 和 stderr 连接到/dev/console",因此信息他们打印到控制台.您可以通过启动控制台应用程序(在 Utilities 文件夹中),但是,它是不方便必须在单独的窗口中查看.另一种选择是将进程的stdout或stderr连接到终端设备对于 GDB 的终端窗口.清单 9 展示了如何做到这一点.

清单 9. 将 stdout 和 stderr 连接到 GDB 的终端设备.

(gdb) 附加 795[...输出省略...](gdb) 调用 (void) DebugPrintMenuList()无输出)-:关闭 stdout 和 stderr 文件描述符.(gdb) 调用 (void) 关闭 (1)(gdb) 调用 (void) 关闭 (2)确定 GDB 本身的终端设备名称.(gdb) 外壳 tty/开发/ttyp1重新打开 stdout 和 stderr,但连接到 GDB 的终端.函数结果应该是1和2;如果没有,某事是非常错误的.(gdb) 调用 (int) open("/dev/ttyp1", 2, 0)1 美元 = 1(gdb) 调用 (int) open("/dev/ttyp1", 2, 0)2 美元 = 2再次尝试 DebugPrintMenuList.(gdb) 调用 (void) DebugPrintMenuList()耶输出!索引 MenuRef ID 标题----- ---------- ---- -----<常规菜单>00001 0x767725D3 -21629 编辑00002 0x76772627 1128 <苹果>00003 0x767726CF 1129 文件00004 0x76772567 1130 编辑[...剩余的输出省略...]

I'm just getting started with Apple Watch. I found instructions from "Five Minute Watchkit", on getting the iOS app and the watch kit app both running in the simulator and both processes attached to the LLDB debugger.

What I do is launch and quit the iOS app to install a current version in the sim. Then I switch to the watchKit scheme and launch that, which displays my watch app UI on the watch simulator.

I then launch the corresponding iOS app in the simulator, then user "attach to process" in the Xcode menu to attach the debugger to the running iOS app.

This works. I can set breakpoints in either the watch kit InterfaceController or in my iOS app and the debugger breaks there when it should.

However, I'm not seeing NSLog() statements in the debug console from my iOS app. (I do see log statements from the WatchKit extension code.) If I set a breakpoint in my iOS app, it does stop at that breakpoint when it should. I assume the lack of console output from NSLog has SOMETHING to do with attaching to a running process on the sim rather than launching it from Xcode, but I don't know what that something is.

(BTW, attaching an action to a breakpoint that invokes NSLog from the breakpoint also doesn't display, but the "log message" debugger command DOES display. Does anybody have any insights?)

EDIT: The code in the iOS app doesn't seem to matter. In my case, it was a dirt simple IBAction that was attached to a button in the iOS app storyboard:

- (IBAction)buttonAction:(UIButton *)sender;
{
  NSLog(@"Button clicked on iPhone");
}

I can set a breakpoint on that NSLog statement. The debugger stops at that line, but I don't see the log statement in the debug console.

解决方案

I can reproduce that with a simple test app, sans WatchKit. The app consists of a NSTimer that prints "Timer fired" every second. (This code is 100% correct ;). Nothing shows in the log after I have manually attached to the process.
As far as I know NSLog outputs to stderr, I guess attaching the debugger does not redirect stderr to the Xcode terminal.

If you are okay with using the console app or the terminal to look at your logs you can do that. iOS8 stores simulator logs in ~/Library/Logs/CoreSimulator/<Device-UUID>. In this directory you will find a system.log, which contains all your NSLog output.

You can look at it in terminal (cat, grep, tail), or open it in the Console.app.


Apple confirms that (at least for GDB) in Technical Note TN2239: iOS Debugging Magic.

Console Output

Many programs, and indeed many system frameworks, print debugging messages to stderr. The destination for this output is ultimately controlled by the program: it can redirect stderr to whatever destination it chooses. However, in most cases a program does not redirect stderr, so the output goes to the default destination inherited by the program from its launch environment. This is typically one of the following:

  • If you launch a GUI application as it would be launched by a normal user, the system redirects any messages printed on stderr to the system log. You can view these messages using the techniques described earlier.
  • If you run a program from within Xcode, you can see its stderr output in Xcode's debugger Console window (choose the Console menu item from the Run menu to see this window).

Attaching to a running program (using Xcode's Attach to Process menu, or the attach command in GDB) does not automatically connect the program's stderr to your GDB window. You can do this from within GDB using the trick described in the "Seeing stdout and stderr After Attaching" section of Technical Note TN2030, 'GDB for MacsBug Veterans'.

The mentioned TN2030 is no longer available on their server (mirror). It showed how you can redirect stdout and stderr to the Xcode console. However, since shell tty isn't a valid command for LLDB it won't help much. But maybe there is a different way to access the tty Xcodes console uses, so I attach the important part of that TN.

Seeing stdout and stderr After Attaching

If you attach GDB to a process (as opposed to starting the process from within GDB), you won't be able to see anything that the process prints to stdout or stderr. Programs launched by the Finder typically have stdout and stderr connected to "/dev/console", so the information they print goes to the console. You can view this by launching the Console application (in the Utilities folder), however, it's inconvenient to have to look in a separate window. Another alternative is to connect the process's stdout or stderr to the terminal device for GDB's Terminal window. Listing 9 shows how to do this.

Listing 9. Connecting stdout and stderr to GDB's terminal device.

(gdb) attach 795
[... output omitted ...]
(gdb) call (void) DebugPrintMenuList()
 No output )-:

 Close the stdout and stderr file descriptors.
(gdb) call (void) close(1)
(gdb) call (void) close(2)

 Determine the name of the terminal device for GDB itself.
(gdb) shell tty
/dev/ttyp1

 Reopen stdout and stderr, but connected to GDB's terminal.
 The function results should be 1 and 2; if not, something
 is horribly wrong.
(gdb) call (int) open("/dev/ttyp1", 2, 0)
$1 = 1
(gdb) call (int) open("/dev/ttyp1", 2, 0)
$2 = 2

 Try the DebugPrintMenuList again.
(gdb) call (void) DebugPrintMenuList()
 Yay output!
Index MenuRef     ID  Title
----- ---------- ---- -----
<regular menus>
00001 0x767725D3 -21629 Ed
00002 0x76772627 1128 <Apple>
00003 0x767726CF 1129 File
00004 0x76772567 1130 Edit
[... remaining output omitted ...]

这篇关于Xcode 附加到进程不显示 NSLog的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆