[Flash/Flex] 使用gdb调试多线程FlasCC应用程序
来源:互联网 发布:开博尔网络机顶盒故障 编辑:程序博客网 时间:2024/05/18 03:33
多线程C/C++程序使用pthread库可以被FlasCC编译,在Flash Player11.5或以上版本中运行。
我们开始吧!
我们将使用一个非常简单的多线程C程序,文件名sample.c,它来自这个优秀的pthreads多线程教程:
这段代码创建一些线程将字符输出到屏幕上。首先使用gcc将代码编译到SWF。
现在使用gdb运行这个SWF。
在PrintHello函数前增加一个breakpoint,并运行程序:
注意PrintHello函数仍被FlashPlayer执行了,这是因为在默认情况下,gdb只在主线程执行,为了对其他线程进行操作,我们需要打开gdb的多线程支持。为此,我们需要启用gdb的"non-stop"模式。"non-stop"模式是指当程序中一个线程停止时,其他线程不受影响。当插入或在后台执行新的命令行,gdb会提示你输入下一个命令而原来的代码执行不受影响。当后台代码执行结束,gdb会通知你。在此模式下,FlasCC允许你单独控制所有线程。
"non-stop"模式与gdb默认的"all-stop"模式略有不同。在"all-stop"模式中,gdb同时执行所有命令,这意味着只有在所有命令执行结束,才可以输入新命令。在此模式下,gdb会忽略主线程以外的其他线程。注意这是gdb的特定行为,转而言之,"all-stop"模式是指程序中的一个线程停止,其他所有线程也将停止。
我们按CTRL+C退出gdb会话,选择Y。
重新启动gdb,我们尝试使用"non-stop"模式。
"non-stop"模式调试程序
"non-stop"模式必须在开运行程序前启用,为此你需要调用3个命令:
技巧:如果你讨厌每次输入这些命令,你可以在a.gdbinit文件中自定义一个gdb命令。
.gdbinit文件会在gdb每次启动时自动加载,它可以放在根目录或当前目录,这样下次启动gdb时,你只需要输入一行代码就可以启用"non-stop"模式。
现在我们已经准备好调试程序,首先设置一个breakpoint在main:
运行SWF:
程序需要几秒加载,然后在main这中断了。你可以忽略[Worker 1]#1的输出,直到确认程序在main这中断了。
目前为止这与默认模式的gdb很相似,但这也是事情发生变化的地方。也许你想让代码继续执行,当你这样做的时候你会看到错误提示:
gdb报告说虽然线程被中断,可是该线程仍然在运行。你可能不理解为什么会有2个线程?毕竟在这段代码中,我们没有使用多线程。原因在于起用多线程支持后,FlasCC会创建后台线程执行程序,这允许你对C代码进行多种操作而不影响UI。你可以使用info threads命令查看运行程序的线程:
你可以看到线程2,代码在18行处中断了,而线程1,UI线程仍然在运行。为了管理UI事件,UI线程负责管理其他较低级别的线程。由于这个原因,如果你想其他线程能够顺畅运行,最好不要中断UI线程。
*表示当前gdb中选择的程序。可以使用线程命令改变gdb当前选择的线程。我们来选择线程2。
现在再试一下step,输入2次:
在这里我们使用pthread_create函数创建一个线程。该线程将调用PrintHello函数。如果你注意观察sample.c的源代码,会发现我们实际是在一个for循环中创建大量的线程。我们中断了PrintHello函数,所以我们可以完全控制每一个线程,创建或调用PrintHello函数。
现在所处的线程是运行步进的,我们来看看会发生什么:
如果你仔细看会觉得有点怪。当你跳过执行这一行代码,gdb提示一切正常,同时另一个线程开始调用PrintHello ,很快它执行到中断处,输出到屏幕上。别担心一切正常。你会发现你仍然可以输入gdb命令,即使你没有看见任何提示符。
如果你想找回提示符,使用CTRL+C即可。CTRL+C,然后使用info threads命令查看线程:
使用step命令
切换到Id3线程,使用2次step命令:
我们看到PrintHello函数的最后一行pthread_exit()被执行。如果我们多执行一次step命令,意味着这个线程执行结束,我们将看不到任何输出:
不用担心这也是正常的。step命令会gdb跳过当前行,直接运行下一行代码。然而在这种情况下,pthread_exit()会导致调用进程终止,没有返回值也不会继续运行下一行(线程已运行结束)。gdb会等待是否有新命令输入。你可以按下CTRL+C中断gdb,再按下CTRL+C获得提示符,然后使用info threads命令查看线程:
注意Id3线程已终止,没有显示在线程列表里,也没有*当前选择的线程。现在我们回到被挂起的线程2:
如果我们执行4次step命令,将创建1个新线程调用PrintHello函数。
CTRL+C,然后选择新线程:
使用continue命令
这次我们试试continue命令:
当gdb continue线程,会在中断处一直等待,直到你输入新的命令。在这里线程2被挂起,线程4已结束,除非我们恢复线程2,否则程序不会再运行到中断处。为了继续调试程序,我们需要中断gdb并恢复线程2。CTRL+C中断gdb,再按下CTRL+C获得提示符,然后使用info threads命令查看线程:
返回主线程,然后执行4次step命令,创建新线程。
按下CTRL+C获得提示符,然后切换到Id5线程:
使用continue&命令
再次执行continue命令,与上次稍有不同,使用的命令是continue&。&符号表示这是一个异步命令,gdb会提示你输入下一个命令。
这个命令允许我们继续长时间运行线程,同时允许我们继续输入新命令及调试其他线程。本教程最后附有一个表格,显示所有&支持的命令。
如果现在执行info threads,我们会看到这个线程运行完毕。
这种情况下使用continue&很方便,因我们不需要在线程结束后按CTRL+C。
我们回到 主线程,执行continue&:
仔细观察你会发现当其他线程运行到中断处,提示符就会出现。按下CTRL+C获得提示符。
使用thread apply命令
在调试多线程应用时,可能有很多线程,你需要经常在线程之间切换。thread apply是一个很方便的命令。它允许你为一系列线程调用相同的命令。举例,我们来backtrace2个线程到PrintHello中断处。
你也可以通过thread apply all将命令适用于所有线程。
结论
现在你知道怎样在gdb中调试多线程的FlasCC程序。如果你有任何问题请在下面留言。但最好还是FlasCC论坛提交你的问题。如果你还没有注册,请点击这里。
命令摘要
以下是常用的调试命令
以下命令支持& 异步
更多参考资料
我们开始吧!
我们将使用一个非常简单的多线程C程序,文件名sample.c,它来自这个优秀的pthreads多线程教程:
这段代码创建一些线程将字符输出到屏幕上。首先使用gcc将代码编译到SWF。
现在使用gdb运行这个SWF。
在PrintHello函数前增加一个breakpoint,并运行程序:
注意PrintHello函数仍被FlashPlayer执行了,这是因为在默认情况下,gdb只在主线程执行,为了对其他线程进行操作,我们需要打开gdb的多线程支持。为此,我们需要启用gdb的"non-stop"模式。"non-stop"模式是指当程序中一个线程停止时,其他线程不受影响。当插入或在后台执行新的命令行,gdb会提示你输入下一个命令而原来的代码执行不受影响。当后台代码执行结束,gdb会通知你。在此模式下,FlasCC允许你单独控制所有线程。
"non-stop"模式与gdb默认的"all-stop"模式略有不同。在"all-stop"模式中,gdb同时执行所有命令,这意味着只有在所有命令执行结束,才可以输入新命令。在此模式下,gdb会忽略主线程以外的其他线程。注意这是gdb的特定行为,转而言之,"all-stop"模式是指程序中的一个线程停止,其他所有线程也将停止。
我们按CTRL+C退出gdb会话,选择Y。
重新启动gdb,我们尝试使用"non-stop"模式。
"non-stop"模式调试程序
"non-stop"模式必须在开运行程序前启用,为此你需要调用3个命令:
技巧:如果你讨厌每次输入这些命令,你可以在a.gdbinit文件中自定义一个gdb命令。
.gdbinit文件会在gdb每次启动时自动加载,它可以放在根目录或当前目录,这样下次启动gdb时,你只需要输入一行代码就可以启用"non-stop"模式。
现在我们已经准备好调试程序,首先设置一个breakpoint在main:
运行SWF:
程序需要几秒加载,然后在main这中断了。你可以忽略[Worker 1]#1的输出,直到确认程序在main这中断了。
目前为止这与默认模式的gdb很相似,但这也是事情发生变化的地方。也许你想让代码继续执行,当你这样做的时候你会看到错误提示:
gdb报告说虽然线程被中断,可是该线程仍然在运行。你可能不理解为什么会有2个线程?毕竟在这段代码中,我们没有使用多线程。原因在于起用多线程支持后,FlasCC会创建后台线程执行程序,这允许你对C代码进行多种操作而不影响UI。你可以使用info threads命令查看运行程序的线程:
你可以看到线程2,代码在18行处中断了,而线程1,UI线程仍然在运行。为了管理UI事件,UI线程负责管理其他较低级别的线程。由于这个原因,如果你想其他线程能够顺畅运行,最好不要中断UI线程。
*表示当前gdb中选择的程序。可以使用线程命令改变gdb当前选择的线程。我们来选择线程2。
现在再试一下step,输入2次:
在这里我们使用pthread_create函数创建一个线程。该线程将调用PrintHello函数。如果你注意观察sample.c的源代码,会发现我们实际是在一个for循环中创建大量的线程。我们中断了PrintHello函数,所以我们可以完全控制每一个线程,创建或调用PrintHello函数。
现在所处的线程是运行步进的,我们来看看会发生什么:
如果你仔细看会觉得有点怪。当你跳过执行这一行代码,gdb提示一切正常,同时另一个线程开始调用PrintHello ,很快它执行到中断处,输出到屏幕上。别担心一切正常。你会发现你仍然可以输入gdb命令,即使你没有看见任何提示符。
如果你想找回提示符,使用CTRL+C即可。CTRL+C,然后使用info threads命令查看线程:
使用step命令
切换到Id3线程,使用2次step命令:
我们看到PrintHello函数的最后一行pthread_exit()被执行。如果我们多执行一次step命令,意味着这个线程执行结束,我们将看不到任何输出:
不用担心这也是正常的。step命令会gdb跳过当前行,直接运行下一行代码。然而在这种情况下,pthread_exit()会导致调用进程终止,没有返回值也不会继续运行下一行(线程已运行结束)。gdb会等待是否有新命令输入。你可以按下CTRL+C中断gdb,再按下CTRL+C获得提示符,然后使用info threads命令查看线程:
注意Id3线程已终止,没有显示在线程列表里,也没有*当前选择的线程。现在我们回到被挂起的线程2:
如果我们执行4次step命令,将创建1个新线程调用PrintHello函数。
CTRL+C,然后选择新线程:
使用continue命令
这次我们试试continue命令:
当gdb continue线程,会在中断处一直等待,直到你输入新的命令。在这里线程2被挂起,线程4已结束,除非我们恢复线程2,否则程序不会再运行到中断处。为了继续调试程序,我们需要中断gdb并恢复线程2。CTRL+C中断gdb,再按下CTRL+C获得提示符,然后使用info threads命令查看线程:
返回主线程,然后执行4次step命令,创建新线程。
按下CTRL+C获得提示符,然后切换到Id5线程:
使用continue&命令
再次执行continue命令,与上次稍有不同,使用的命令是continue&。&符号表示这是一个异步命令,gdb会提示你输入下一个命令。
这个命令允许我们继续长时间运行线程,同时允许我们继续输入新命令及调试其他线程。本教程最后附有一个表格,显示所有&支持的命令。
如果现在执行info threads,我们会看到这个线程运行完毕。
这种情况下使用continue&很方便,因我们不需要在线程结束后按CTRL+C。
我们回到 主线程,执行continue&:
仔细观察你会发现当其他线程运行到中断处,提示符就会出现。按下CTRL+C获得提示符。
使用thread apply命令
在调试多线程应用时,可能有很多线程,你需要经常在线程之间切换。thread apply是一个很方便的命令。它允许你为一系列线程调用相同的命令。举例,我们来backtrace2个线程到PrintHello中断处。
你也可以通过thread apply all将命令适用于所有线程。
结论
现在你知道怎样在gdb中调试多线程的FlasCC程序。如果你有任何问题请在下面留言。但最好还是FlasCC论坛提交你的问题。如果你还没有注册,请点击这里。
命令摘要
以下是常用的调试命令
- info threads 显示线程列表
- thread X 设置选定线程的Id
- thread apply X Y 对指定线程X执行指定命令Y 例子:thread apply 3 4 step
- thread apply all Y 对所有线程X执行指定命令Y 例子:thread apply all step
以下命令支持& 异步
- step& 跳过本行代码(进行子程序调用)
- next& 将程序移动到下一行代码(进行子程序调用)
- continue& 继续执行当前选定线程
更多参考资料
- 使用gdb发现多线程bug
- 使用多线程Debug程序
- gdb"non-stop"模式
- gdb"all-stop"模式
- POSIX线程编程
原文链接:http://blogs.adobe.com/flascc/2012/11/09/debugging-multi-threaded-flascc-applications-with-gdb/
- [Flash/Flex] 使用gdb调试多线程FlasCC应用程序
- [Flash/Flex] FlasCC配置脚本的使用
- [Flash/Flex] 使用gdb查找多线程bug
- [Flash/Flex] 使用Flash的C++编译器Flascc的提示和窍门
- [Flash/Flex] FlasCC 的1.0 版本发布
- 使用gdb调试多线程
- 使用gdb 调试多线程
- 使用gdb调试多线程程序- -
- 使用gdb调试多线程死锁
- 使用GDB调试多线程程序
- 使用gdb调试多线程程序
- 如何使用GDB调试多线程
- 如何使用GDB调试多线程
- 使用gdb调试多进程多线程调试
- Linux下使用GDB调试应用程序示例
- 使用gdbserver+arm-linux-gdb 调试应用程序
- 使用gdb调试多线程程序总结
- 使用GDB时,调试多线程的方法
- php:reset函数
- JSTL fn:${fn:split(str, ",")}
- [Flash/Flex] 使用gdb查找多线程bug
- Hibernate你必须知道的六个方面
- SKU
- [Flash/Flex] 使用gdb调试多线程FlasCC应用程序
- socket编程中的一些问题(3)
- 将一个整数M分成N个数相加的和,要求每个数至少要大于等于1
- play framework2开发(二)
- [Flash/Flex] FlasCC:如何在AS项目中调用多个SWC
- Linux 调优方案, 修改最大连接数(ulimit命令)
- 原味
- Java初始化顺序
- IDocHostUIHandler::ShowContextMenu添加自定义菜单的另类实现