1.system.getproperty('java.class.path')是调试调试在什么时候被设
2.xcode调试心得
3.macos系统上调试FFmpeg的三种方式
4.Mac 下的 C++ 开发环境 XCODE和其他介绍
5.开发工具有哪些
6.通过 JetBrains Rider 或 Visual Studio 对虚幻引擎项目进行断点调试
system.getproperty('java.class.path')是在什么时候被设
系统属性java.class.path的设置确实隐藏且复杂,我通过lldb调试工具找到其被加入SystemProperty的无源源头。我使用的调试调试是OpenJDK 9源代码进行调试,具体定位在了以下地址:github.com/dmlloyd/open...
在该源代码中,无源java.class.path属性值被成功加入到系统属性链表。调试调试详情请参考上述链接,无源lis系统pb源码深入理解其设置过程。调试调试
xcode调试心得
没有系统的无源学习和总结过Xcode调试相关的知识,这里参考/里面的调试调试教程,总结一下调试相关的无源知识,算半拉翻译,调试调试半拉总结吧崩溃的无源表现一般来说:
SIGABRT(好处理)
EXC_BAD_ACCESS(一般内存问题)
SIGBUS
SIGSEGV
左面工具栏会按照线程分出bug所在,thread1一般主线程,调试调试其他线程的无源问题会在自己的位置显示。点开里面的调试调试方法都是看不懂的汇编(其实以前学过)。
对于Xcode下方有提示的bug一般很好解决,但是有时候只是简单的EXC_BAD_ACCESS,无从下手,左面工具栏中的方法也看不出所以然,这时要把顶部工具栏的breakpoint打开,也许左面就会显示出更多出问题的方法,如图打开brekpoints以后多出了所选的方法提示,找到了是数组的问题。当然也可以在左面下方滑块调节来显示出更多提示的方法。
总结的来说,就是在左面栏里找到出问题的地方
App启动的流程
上面的图的调用关系说明了App是怎么启动的,除了main方法,其他方法都是看不到的,默认封装到系统的framework里,没法看源码
方法引用错误一般来说:
[UINavigationController setList:]: unrecognized selector sent to instance 0x6d4ed
1 [UINavigationController setList:]: unrecognized selector sent to instance 0x6d4ed这种要不就是这个类没这个方法,或者调用方法的对象错误,或者拼错,比较简单
看打印信息
没有打印信息的时候,可以点这个,有时候需要多点几次,可以有更详细的错误打印信息,lldb调试输入c功能是一样的,都是InvocationHandler源码让程序继续运行
This class is not key value coding-compliant
Problems[:f] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is notkey value coding-compliant for the key button.'
12
3
4
5 Problems[:f] *** Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[ setValue:forUndefinedKey:]: this class is not
key value coding-compliant for the key button.'
1.有时会碰到这种错误,印象里是请求的网络列表返回为空,出现了个这么诡异的现象,这是一种情况。
2.NSUnknownKeyException指示了未知的key,而这个未知的key出现在MainViewController里,这个key的名字是button
先看nib,在这个例子里有一个button,和MainViewController的属性button连接了IBOutlet,但是@property对应的@synthesize没有写,出现了这个问题,虽然在iOS6可以不用写@synthesize了,但是在老版本可能还会出现这个问题
3.总结一下,“This class is not key value coding-compliant”这个问题出现在NIB相关的地方,一般是iboutlet已经连接,但是这个属性却不存在,常常发生在ib连着呢,属性给删了。
使用DEBUGGER
[self performSegueWithIdentifier:@"ModalSegue" sender:sender];
1 [self performSegueWithIdentifier:@"ModalSegue" sender:sender];这句话出问题了,不知道怎么处理,可以在左面选中抛出的异常expection_throw
用LLDB的debugger po $eax会调用description方法,打印全部信息
po是point object,$eax是当前cpu注册者之一,如果选中了异常错误输入这个命令,这个注册者就是NSException对象,注意$eax是用于模拟器的,真机要用$r0
可以看大原因了,是segue问题,storyboard中的问题这里就定位了
类似的,还有这些debugger方法
po [$eax class] //可以看到 (id) $2 = 0xe NSException,数字不重要NSException是问题的名字po [$eax name]//得到exception的名字po[$eax reason]//得到错误原因(unsigned int) $4 = Receiver () has no segue with identifier 'ModalSegue'
12
3
4
5 po [$eax class] //可以看到 (id) $2 = 0xe NSException,数字不重要NSException是问题的名字
po [$eax name]//得到exception的名字
po[$eax reason]//得到错误原因(unsigned int) $4 = Receiver () has no segue with identifier 'ModalSegue'
NSAssert用法
- (void)doSomethingWithAString:(NSString *)theString{ NSAssert(theString != nil, @"String cannot be nil");NSAssert([theString length] = 3, @"String is too short");. . .}
12
3
4
5
6
7
8
9
- (void)doSomethingWithAString:(NSString *)theString
{
NSAssert(theString != nil, @"String cannot be nil");
NSAssert([theString length] = 3, @"String is too short");
. . .
}
NSAssert最为一种防御型的代码,目的就是一有错,程序就伴随着异常崩溃,或者说停止运行,不往下进行。上面的代码当传入空数组的时候就会打印这个:
-- ::. Problems[:c] *** Assertion failure in -[MainViewController doSomethingWithAString:], /Users/lipengxuan/Downloads/Problems/Problems/MainViewController.m:
1 -- ::. Problems[:c] *** Assertion failure in -[MainViewController doSomethingWithAString:], /Users/lipengxuan/Downloads/Problems/Problems/MainViewController.m:有的时候程序崩溃打印信息就会出现Assertion,那么就是这句话起作用了,这个时候可以继续运行(lldb c),可以看到更详细的880006源码打印信息。
总结一下,遇到Assertion failure,就可以下一步运行看更详细的信息
BreakPoint使用breakpoint 分Exception breakPoint和breakPoint
Exception breakPoint:程序崩溃异常了会立刻暂停到断点,点加号第一个就是添加Exception断点
breakPoint:随意放
Finally!终于到了传说中的打断点,这个很基本很经典的调试方法,事实上,断点和NSLog用法差不多,只不过不用你去写了
一个简单的例子,现在有个这么个方法
- (id)initWithStyle:(UITableViewStyle)style{ NSLog(@"init with style");if (self == [super initWithStyle:style]){ list = [NSMutableArray arrayWithCapacity:];[list addObject:@"One"];[list addObject:@"Two"];[list addObject:@"Three"];[list addObject:@"Four"];[list addObject:@"Five"];}return self;}
12
3
4
5
6
7
8
9
- (id)initWithStyle:(UITableViewStyle)style
{
NSLog(@"init with style");
if (self == [super initWithStyle:style])
{
list = [NSMutableArray arrayWithCapacity:];
[list addObject:@"One"];
[list addObject:@"Two"];
[list addObject:@"Three"];
[list addObject:@"Four"];
[list addObject:@"Five"];
}
return self;
}
程序运行后我发现貌似这个方法没有执行,这是一种猜测,通常我会在方法里加入打印信息,也可以打断点,在方法定义的地方加断点,如果调用这个方法了,就会停止在这里,起到了一样的作用。
接着是单步调试
打断点,然后点击跳跃的箭头,就可以一步步的执行了,更精细的步骤可以F6,期间可以随时打印想看的变量,比如在tableview的cellForRowAtIndexPath函数中用po indexPath打印出indexPath的值
(NSIndexPath *) $3 = 0x 2 indexes [0, 1]
1 (NSIndexPath *) $3 = 0x 2 indexes [0, 1]意思就是section 0 row 1
这样进行一步打印一次,可以看出indexes也在变化,知道出问题的敌方
Problems[:f] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]'*** First throw call stack:(NSIndexPath *) $ = 0xa8a6c0 2 indexes [0, 5]
12
3
4
5
6
7 Problems[:f] *** Terminating app due to uncaught exception 'NSRangeException',
reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]'
*** First throw call stack:
(NSIndexPath *) $ = 0xa8a6c0 2 indexes [0, 5]
单步调试找出来了index row=5超出了数组的范围
总结一下,po命令非常实用,只要找到正确的调用方法,就可以打印对象信息
ZOMBIES问题EXC_BAD_ACCESS问题一般是内存问题,比如下面这种情况
程序停在了这里,EXC_BAD_ACCESS问题,但是也不知道具体问题是什么,这时候可以用zombie 工具检测
Xcode点击左上角项目名字-Edit Scheme-Diagnostics-Enable Zombie Objects,OK再次运行
会多出这段话
-- ::. Problems[:c] *** -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0xcbe
1 -- ::. Problems[:c] *** -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0xcbe这段话什么意思呢?
创建一个对象,alloc一个对象会分配给这个对象一块内存,党这个对象release了,引用计数归零了,这块内存就会dealloc掉,-43 源码之后其他对象就可以用这块内存。
但是可能有这样一种情况,正在有对象使用的内存被另一个对象企图指向使用,或者已经被释放的内存企图再次被释放。
僵尸工具的作用是让对象被released的时候,内存不dealloc,这块内存被标记为“undead”,如果其他对象想再用这块内存,app可以识别出错误并显示“message sent to deallocated instance”,就像上面的那段话一样。结合上面的代码
cell.textLabel.text = [list objectAtIndex:indexPath.row];
1 cell.textLabel.text = [list objectAtIndex:indexPath.row];这段话就是zombie对象出现的地方,一般来说textLabel 还有indexPath.row应该没问题,问题应该出现在list这个数组,而且zombie tool也说了是[__NSArrayM objectAtIndex:]的问题,利用NSLog打印list,可以看到内存地址和错误的地址相同,那么错误就定义在list了
-- ::. Problems[:c] list is 0xb0ed-- ::. Problems[:c] *** -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0xb0ed0
12
3 -- ::. Problems[:c] list is 0xb0ed0
-- ::. Problems[:c] *** -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0xb0ed0
当然用dubugger 命令 p list也可以打印出这个结果
这就是zombie 工具起的作用,解决内存问题
总结的来说,如果出现了EXC_BAD_ACCESS错误,打开僵尸工具,再试一遍。但是没问题的时候不要打开这个工具,因为这个工具从不dealloc内存,只是标记内存为”undead”,会导致内存泄露,所以用的时候再打开,诊断后再关掉。
习惯问题应该看bug一样的视线看warning,能修复就修复。
- (void)buttonTapped:(id)sender{ NSLog(@"You tapped on: %s", sender);}
12
3
4
5
6
7 - (void)buttonTapped:(id)sender
{
NSLog(@"You tapped on: %s", sender);
}
比如这个按钮点击事件,%s是打印C-String,就是末尾是NUL的字符串,但是这里sender是按钮对象,所以会崩溃,不能忽略警告
macos系统上调试FFmpeg的三种方式
macOS系统上调试FFmpeg的三种途径
FFmpeg作为一款强大的多媒体处理框架,其与现代技术的结合需求使得调试变得至关重要。本文将指导你如何在macOS上单步调试FFmpeg的WCDB源码代码,以深入理解程序运行和定位问题。
首先,理解调试的重要性。通过调试,你可以跟踪程序执行流程,直观地观察变量变化,这对于理解代码逻辑和定位bug极其有用。尽管阅读源码可以提供基础理解,但动态调试能让你实时操作代码,提高效率。
在macOS上进行调试,你需要从下载FFmpeg源码开始。通过Git或直接下载压缩包,确保你的开发环境具备查看源码的工具,如Source Insight、Sublime Text或VS Code等。对于不熟悉的人来说,这可能需要一些软件基础的学习。
在编译FFmpeg时,建议使用Xcode,因为它自带的编译器会简化过程。即使你选择不使用Xcode,gdb和lldb也是调试工具的选择。在编译时,取消优化选项可以方便调试,然后只需运行make命令即可。make clean用于清理上一轮编译,make install则会安装FFmpeg,但对调试来说无必要。
接下来,可以使用gdb进行命令行调试,通过ffplay的调试版本来切入。理解带_g的程序是调试用的,能提供更多的调试信息。而在Xcode中,通过创建新项目,引用FFmpeg库,添加符号信息,你可以在main函数上设置断点,直接跳转到FFmpeg的源码进行调试。
总的来说,调试FFmpeg在macOS上有多种方式,无论你选择哪种,关键在于熟悉工具和配置,以便更有效地进行代码探索和问题解决。
Mac 下的 C++ 开发环境 XCODE和其他介绍
Xcode,版本4.6.3,内置了创建C++项目的功能,操作步骤如下:首先打开Xcode并新建项目,选择OS X中的Application内的Command Line Tool选项,然后在项目设置中选择Type为C++。若不需要使用自动引用计数(ARC),取消勾选C++选项。完成这些步骤后,即可在Xcode中创建一个基础的C++项目。
值得注意的是,Xcode默认使用的C++编译器是Apple LLVM Compiler(4.6.3版本为4.2),默认标准库为libc++,已支持C++标准(先前的C++0x)。Xcode同时提供了LLVM GCC编译器,其附带的C++标准库为libstdc++。在引入第三方库时,需特别注意选择,例如OpenCV可能需要将标准库设置为libstdc++。
如果选择不使用IDE,直接通过命令行编译C++项目也很容易,只需要使用编译器即可。
接下来,我们简要介绍C++的编译过程。编译过程包含预处理、编译和链接等步骤,目的是从源代码生成可执行文件。compiling仅是整个build过程的一部分,但人们经常会误将compile视为整个过程。通常情况下,这些步骤由编译器自动完成,无需单独运行命令。
Mac上默认拥有LLVM和GCC两大编译工具。
LLVM起源于“Low Level Virtual Machine”项目,由Chris Lattner和Vikram Adve于年在伊利诺伊大学厄巴纳-香槟分校开始。年Apple雇佣了Chris Lattner,组建团队专注于LLVM在Apple开发系统上的应用。目前,LLVM是MacOS和iOS开发工具的关键组成部分。
LLVM项目是一个综合项目,包括了一系列与开发工具相关的技术,如编译器Clang、调试器LLDB、JIT系统VMKit、优化器DragonEgg等。
GCC,全称为GNU Complier Collection,是GNU项目的核心组成部分,由自由软件之父Richard Stallman于年发起。GCC最初只支持C语言编译,1.0版本后开始支持C++,随后支持了Objective-C、Objective-C++、Fortran、Java、Ada、Go等其他语言。
选择LLVM或GCC取决于具体需求。GCC历史悠久,支持范围广泛,许多开源项目直接使用GCC作为编译器。而LLVM相较于GCC的优势在于:编译速度快、内存占用小、模块化设计易于集成及其他用途的重用、诊断信息可读性强、设计清晰简单、易于理解和扩展。通过GCC和Clang的相应编译选项,可以查看build过程的各个步骤,如仅执行预处理、编译阶段或生成对应名称的对象文件等。
关于GCC和Clang的编译选项,通过man gcc和man clang可以获取更多详细信息。
开发工具有哪些
在软件开发行业中,开发工具是非常重要的一部分。好的开发工具可以让开发过程更加高效、快捷。那么,开发工具有哪些呢?
1. 集成开发环境(IDE)
集成开发环境是一个软件应用程序,利用它可以进行软件开发。IDE 提供了完整的开发工具在一个集成的开发环境中,包括代码编辑器、版本控制、构建自动化等。常见的 IDE 包括 Eclipse、Visual Studio、IntelliJ IDEA 等。
2. 代码编辑器
代码编辑器是一种软件应用程序,它的功能是用于编写和修改源代码。代码编辑器通常集成了语法高亮、代码补全、自动格式化等功能,可以大大提高开发效率。常见的代码编辑器包括 Sublime Text、Atom、Visual Studio Code 等。
3. 版本控制工具
版本控制工具是用于管理源代码的历史和修改的工具。它们可以跟踪每个文件的更改、确定谁做了某个修改、为不同版本的文件保留备份等。常见的版本控制工具包括 Git、SVN 等。
4. 单元测试工具
单元测试是一种软件测试方法,用于测试代码的最小单元(如一个函数或方法)是否正常运行。单元测试工具可以帮助程序员编写和运行测试用例,以确保代码的质量和可靠性。常见的单元测试工具包括 JUnit、NUnit 等。
5. 构建自动化工具
构建自动化工具用于自动化构建和部署应用程序。构建工具通常会自动执行编译、打包和测试等步骤,以减少手动配置和人为错误。常见的构建自动化工具包括 Maven、Gradle 等。
6. 调试器
调试器是一种工具,用于在调试过程中帮助程序员查找和修复程序中的错误。调试器通常提供一组强大的工具,如设置断点、逐行执行、查看变量和表达式的值等。常见的调试器包括 LLDB、GDB、Visual Studio Debugger 等。
7. 代码分析工具
代码分析工具是一种工具,用于找到代码中隐含的错误和潜在的问题。这些工具可以自动分析代码并生成报告,以帮助程序员提高代码质量和可维护性。常见的代码分析工具包括 PMD、FindBugs 等。
总之,好的开发工具可以极大地提高软件开发效率和质量,使程序员可以更加专注于创造出更加优秀的产品。
通过 JetBrains Rider 或 Visual Studio 对虚幻引擎项目进行断点调试
调试虚幻引擎项目时,你可以使用 JetBrains Rider 或 Visual Studio。首先,确保已正常打包 Windows 版本项目,无需特殊处理。
为了进行附加调试,创建一个工程启动快捷方式时,在参数部分添加 "-waitforattach",记得留有空格。接下来,根据IDE选择相应的附加方式:
使用 Rider,找到ID较大的进程,然后在调试选项中选择 LLDB。确保右下角勾选 "Attach with LLDB"。
而在 Visual Studio 中,应选择ID较小的进程,并选择与之相匹配的调试模式。
设置好附加后,你可以开始设置断点,按照需要逐步调试。然而,可能会遇到QA堆栈显示不正确的情况。这通常是由于源代码和符号文件不匹配导致的。如果是本地工程在本地机器上运行,这个问题通常不会出现。但如果涉及到非本地程序,确保源代码路径已配置在符号路径中,以确保正确的符号映射。