编译android 源码编译命令时lunch命令出现的选项都是啥意思

Cygwin下编译包含C的Android源码,出现错误,求大神解答。
------解决思路----------------------
原因和我昨日贴着中问的差不多,但是没有人能回答。
我现在暂时把source和ndk放在一个盘符上,然后通过相对路径的方式暂时使用,等待高手的出手
android出现如下的情况,大神们,谁能给解决一下啊?
NoXMLcontent.Pleaseaddarootvieworlayouttoyourdocument.困扰了我一晚上了。。拜托了
------解决方案-----------------
android ndk如何编译基于mips架构的开源C++库? Androidndkr8支持mips架构了,但是其中提供的交叉工具只有mipsel的,那我要编译mips的怎么办?,求高手指点迷津
------解决方案-------------------- mipsel表示小端编译
mips的编译器表示默认大端
刚开始学android,照着书上例子做出现错误,不懂,代码贴出来高手指教下 建了个工程叫helloandroid。res里面的layout文件代码如下
&LinearLayout android:layout_width=&wrap_content& &nbsp
android升级后无法真机调式求大神帮忙 最近对android的sdk和adt升级,升级到最新androidsdktools21,adt也升级到21,但是原先用于真机调式的manual选项没有了,大侠们帮忙解决下啊如下图:
------解决思路---------------------- 把钩去掉&nb
android 4.0 launcher 2 源码 eclipse可以编译
关于 androidlauncher 2 编译 大家一定都尝试过. 但是 由于种种原因呢 可能是失败了. 今天告诉他家 如何 编译 android launcher 2 在eclipse上 .
如果你编译过 android2.3 以前的 launcher 2 的话 . 那么 你编译 android 4.0
安卓小白请教大神们一个问题,安装SDK出现的问题 大神们,安装SDK的时候出现以下这个错误:
FailedtofetchURLhttps://dl-/android/repository/addons_list.xml,reason:Filenotfound
将修改过的Android 4.0 源码如何正确合理的拷贝到 4.1上 在修改Android系统源码时,比如现在我有两套面向两个不同芯片的4.0.4Android源码,以下简称为A源码,B源码,A/B源码生成的Android系统用户操作及视觉都是一样的。现在我使用A源码生成的systemUI.apk(状态栏)&nbs
android jni开发之cygwin安装
本文出自:/thread-.html
声明:本文部分内容摘自网络,欢迎转载,转载请注明出自:安卓开发网 什么是cygwin?
cygwin是一个在windows平台上运行的unix模拟环境,
2.什么是android ndk?
升级Android SDK到2.3错误的解决办法
升级了2.3的朋友应该知道,升级到2.3后,Eclipse会报错!不能编译运行了,解决办法如下。 1、因为升级后的2.3会在android-sdk-windows下创建一个platform-tools文件夹,其中包含了应该在tools文件夹下的东西,我们只需要将platform-tools文件夹下的所有文件复制到tools目录下。 2、然后在pl
Android 应用读写I2C 我参考别人的用NDK+JNI读写I2C,编译出来的APK可以运行了,但是老读不到数据,这个I2C的地址怎么确认是多少呀?就是slaveAddr的值应应该怎么设置?或者是有什么其它问题?
------解决方案-------------------- I2C是什么?
integertochar?
------解决方案
如何在Ubuntu上下载、编译和安装Android最新源代码
看完了前面说的几本书之后,对Linux Kernel和Android有一定的认识了,是不是心里蠢蠢欲动,想小试牛刀自己编译一把Android源代码了呢?一直习惯使用Windows系统,而Android源代码是不支持在Windows上编译上,于是决定使用虚拟机安装Ubuntu,然后下载、编译和安装Android源代码。 &n
Android 安全攻防(一):SEAndroid的编译
SEAndroid的编译 SEAndroid概述
SEAndroid(Security-Enhanced Android),是将原本运用在Linux操作系统上的MAC强制存取控管套件SELinux,移植到Android平台上。可以用来强化Android操作系统对App的存取控管,建立类似沙箱的执行隔离效果,来确保每一个App之间的独
android4.0 开启硬件加速后应用运行出错
Android4.0 开启硬件加速后部分应用运行出错。
出现异常:
12-20 15:18:19.543: E/AndroidRuntime(26301): FATAL EXCEPTION: main 12-20 15:18:19.543: E/AndroidRuntime(26301): java.lang.UnsupportedOpe
如何导入android sdk 的 sample中的源码
初学Android编程,Android SDK中提供的Sample代码自然是最好的学习材料。
Sample代码在SDK安装目录(X:\Android\android-sdk\samples)下。但我在用Eclipse 开发环境导入的时候遇到了一些麻烦。网上看到有人
Android源码.健康食物
Android源码下载,非常漂亮的android应用,直接导入eclipse便可以使用。
android Application的防反编译Proguard和应用签名
android APK防止反编译: 在android2.3之后的版本新建项目中会自动生成proguard.cfg和project.properties文件,proguard.cfg文件是混淆java代码的配置文件,里面对不需要混淆代码的类文件进行配置过滤,project.properties文件里设置android项目对
四极管:关于__android_log_print错误提示
cm7自己写了一个模块,但是C代码里有用到LOGI,编译的时候报错,说undefinedreferenceto`__android_log_print', 在 Android.mk文件中需要加入:
LOCAL_LDLIBS := -llog
LOCAL_C_IN
求问大神如何解决从后台获取数据是中文乱码问题?
try{ URLurl=newURL(urlstr); URLConnectionconn= try{ conn=url.openConnection(); InputStreamin=conn.getIn
使用Android系统隐藏api读取*.apk程序安装包信息
前提:我们需要得到 Android
系统源码编译输出的一个文件
out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar
这个包里面包含所有的系统api, 隐藏的, 公开的
添加 jar方法
右键功能菜单-&Properties-&
android源码settings中显示所有正在运行进程流程分析
下面我要分享一下这几天看源码中获得正在运行进程的简单流程:
也就是图中所看到的
首先我们看到的是settings下的application(应用程序)下的manageApplication(管理应用程序)下的页面,那么要了解其流程,我们就得到源码中去分析:
那么我们到源码下的package/app/Settings/s
新手请教一个错误问题!感谢!
本帖最后由 meng6979739 于
13:21:12 编辑
新手请教一个错误问题!
下文的代码是参照一本叫《深入浅出_Google_Android》做的实例。
在编译过程中出现了问题,由于本人初学,找遍了资料也没弄明白问题出在哪里,希望大家帮个忙,感激不尽!
packagemm.demo.
android\packages\apps 源码中加了 log.i(&...&); 下载到样机上, log 信息没有输出, 会是什么原因呢? android\packages\apps\VoiceDialer
VoiceDialer源码中加了log.i(&...&);下载到样机上,log&nbs
android反编译问题 反编译之后,源代码的类名都变成a-z这样无意义的名字。请问有没有什么办法能让类名保持原始有意义的名字呢?
------解决方案-------------------- 是这样的,一般用proguard混淆的话,你是该软件的开发者,一般有个mapping.txt映射文件,有对应原始的类名
------解决方案--------------------
android应用程序访问I2C接口
本帖最后由 yiyaaixuexi 于
22:08:39 编辑
最近正在作一个androi的项目,在该项目中需要访问硬件,代码简述如下:
publicnativeintopen(Stringpath);
[个人作品,含源码] Android 程序之在线词典, 觉得有帮助的,请过来顶一下 http://blog.csdn.net/ostrichmyself/archive//4633838.aspx
下面是部分贴图,有兴趣可以到我的博客上瞅瞅,谢谢!
交些Android开发的同道中人(加我为好友,谢谢),本人业余型的
浅析Android下的Android.mk文件
大家都知道在Linux下编辑经常要写一个Makefile文件, 可以把这个Makefile文件理解成一个编译配置文件,它保存着如何编译的配置信息,即指导编译器如何来编译程序,并决定编译的结果是什么。而在Android下的Android.mk文件也是类型的
新建Android程序的时候发生了找不到 \android-sdk-windows\tools\lib\proguard.cfg文件 的错误
在新建Android程序的时候出现以下错误: 找不到 \android-sdk-windows\tools\lib\proguard.cfg文件
原因: SDK不完整。
解决方法: 方法一 可在\andr
修改Android4.0.3桌面图标的行数和列数
上网搜索修改Android桌面图标的行数和列数 修改workspace_screen.xml中增加 launcher:shortAxisCells=&4& launcher:longAxisCells=&4&
发现到Android4.0.3下编译出现出错,可能是4.0以下的版本支持吧 之后到launc
为launcher添加仿HTC的preview(开源,附源码) 最近有时间了,顺便把之前做的一点东西慢慢整理出来,让大家一起研究,讨论下。
Android原生自带的preview不是很好看,很喜欢HTC的,之前看到ADW上也有那样的preview,所以将它提取出来,放入了原生的android2.2中。闲不说,直接上图,有图有真相:
原生的,未修改版本:(B
共享android模拟真实书籍翻页效果(附源码)
发布一个简单的模拟真实书籍翻页效果的源码,记得要顶哦~~~
源码下载地址:http://download.csdn.net/source/3216809
详细的原理分析可以参看我的博客:http://blog.csdn.net/hmg25/archive//6342539.aspx
syslog输出在android平台上如何使用? 在/home/ubuntu/android- x86/bionic/libc/netbsd/net/getaddrinfo.c中出现一些syslog语句,我想知道这些语句打印出来的信息怎么查看?(简单的尝试了一下logcat,没有发现syslog信息输出到了logcat里面)
注:已在此文件中尝试了LOGE,__android_log_print
———android 展示网络上的图片和播放视频
———android 展示网络上的图片和播放视频
1、展示图片: ImageView
&?xml version=&1.0& encoding=&utf-8&?& &LinearLayout xmlns:android=
android apk 无法运行 我在网上下了个apk的游戏,使用cmd————adbinstallaa.dpk命令,成功的将它发布到已经启动好的android虚拟机上,可是当我点击游戏的图标时,却无法正常运行,并强制退出到虚拟机的初始界面。我是个android方面的新手,还希望各位大侠们帮我解答下,呵呵
------解决方
android.content.res.Resources$NotFoundException错误的解决办法
EditText.setText(8);
当使用上面这样的代码时,将报错, 原因是将 这里的8 看为是资源。
正确的使用方法可以这样:
EditText.setText(8+&&);
急求:TabHost下的Tab的activity跳转
TabHost里面的一个内容页是activity,数据来了之后“折线图”要进行更新,所以要能在当前同一个Tab下进行跳转到新的activity....但是我一跳转就会把整个tabHost都抹掉,而不是tabhost里面的内容进行变换...
------解决方案-------------------- 如果仅仅改变折线图,感觉重新画个折线图
关于android源码程序图标问题 下载了一个连连看的源码,想改变apk包和安装后桌面图标的样式,改了AndroidManifest.xml中&application
android:icon=&@drawable/XXX&,可是程序安装后桌面图标还是原先的,工程clean也不行,求教
------解决方案-------------------- 把原来的
求解android电话号码中的特殊字符 昨儿出现了一个测试contacts出现的bug,出错地点是PhoneNumberUtils.charToBCD()。出错原因是java.lang.RuntimeException:invalidcharforBCD;
意思是这个函数中的;号没有做处理。
求问:电话号码中的几个特殊字符是什么意思?
仿Siri的中文语音助理源码 之前闲暇之余借鉴Iris的框架,仿写了一个中文语音助理,效果如下:
语音接口使用的是科大讯飞的云语音接口,具体使用可以到科大讯飞的网站了解,智能语音处理部分使用的是小I聊天机器人的网络接口(/widget/1007/index.html)——用于聊
Android Jamendo源码 图片缓存实现
Jamendo 代码Image缓存实现:
package com.teleca.jamendo. import java.util.WeakHashM import android.graphics.B /** * Caches downloaded images, saves bandwidth and user
android设计求思路
要做一个大致上是手机客户端上传信息到服务器,然后服务器会传到所有客户端的东西,碰到几个问题请教下。 1.选择哪种通信方式较好,个人倾向于socket 2.服务器端用自己的电脑可行吗?(我的想法是在自己电脑建立数据库作为服务器,不知道行不行) &nbsp2456人阅读
Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品,如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要了解下,Android的编译过程。
如果你从来没有做过Android代码的编译,那么最官方的编译过程就是查看Android的官方网站:/source/building.html
但是,这儿只是告诉你了如何去编译一个通用的系统,并没有详细告诉你细节,我们跟着编译过程来了解下。
+-------------------------------------------------------------------------------------------------+
本文使用Android版本为2.1,采用开发板为华清远见研发的FS_S5PC100A8开发板。
+-------------------------------------------------------------------------------------------------+
按照google给出的编译步骤如下:
&& 1& sourcebuild/envsetup.sh:加载命令
&& 2& lunch:选择平台编译选项
&& 3& make:执行编译
我们按照编译步骤来分析编译过程的细节,最终添加自己的平台编译选项。
1. source build/envsetup.sh
这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。
envsetup.sh里的主要命令如下:
function help()                  # 显示帮助信息
function get_abs_build_var()           # 获取绝对变量
function get_build_var()             # 获取绝对变量
function check_product()             # 检查product
function check_variant()             # 检查变量
function setpaths()                # 设置文件路径
function printconfig()              # 打印配置
function set_stuff_for_environment()      & #设置环境变量
functionset_sequence_number()        &&&# 设置序号
function settitle()                # 设置标题
function choosetype()               # 设置type
function chooseproduct()            & #设置product
function choosevariant()            & #设置variant
function tapas()                & #功能同choosecombo
function choosecombo()             & #设置编译参数
function add_lunch_combo()           & #添加lunch项目
function print_lunch_menu()            # 打印lunch列表
function lunch()                 # 配置lunch
function m()                   # make from top
function findmakefile()              # 查找makefile
function mm()                   # make from current directory
function mmm()                 & # make thesupplied directories
function croot()                 # 回到根目录
function cproj()
function pid()
function systemstack()
function gdbclient()
function jgrep()                 # 查找java文件
function cgrep()                & #查找c/cpp文件
function resgrep()
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function godir ()                 # 跳到指定目录 405
&# add_lunch_combo函数被多次调用,就是它来添加Android编译选项
&# Clear this variable.& It willbe built up again when the vendorsetup.sh
&406 # files are included at the end of thisfile.
&# 清空LUNCH_MENU_CHOICES变量,用来存在编译选项
&407 unset LUNCH_MENU_CHOICES
&408 function add_lunch_combo()&
&410&&&&localnew_combo=$1&&&&&&&&# 获得add_lunch_combo被调用时的参数
&411&&&&local c
&&&&# 依次遍历LUNCH_MENU_CHOICES里的值,其实该函数第一次调用时,该值为空
&412&&&&for c in ${LUNCH_MENU_CHOICES[@]} ; do
&413&&&&&&&&if [ &$new_combo& = &$c& ] ;then&&& #如果参数里的值已经存在于LUNCH_MENU_CHOICES变量里,则返回
&414&&&&&&&&&&&&return
&415&&&&&&&&fi
&416&&&&done
&&&&# 如果参数的值不存在,则添加到LUNCH_MENU_CHOICES变量里
&417&&&&LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
# 这是系统自动增加了一个默认的编译项 generic-eng
&420 # add the default one here
&421 add_lunch_combogeneric-eng&&& #调用上面的add_lunch_combo函数,将generic-eng作为参数传递过去
&423 # if we're on linux, add thesimulator.& There is a special case
&424 # in lunch to deal with the simulator
&425 if [ &$(uname)& = &Linux& ] ; then
&426&&&&add_lunch_combo simulator
# 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它
1037 # Execute the contents of any vendorsetup.sh files we canfind.
1038 for f in `/bin/ls vendorbuild/vendorsetup.sh 2&/dev/null`
1040&&&&echo &including $f&
1041&&& .$f&&&&&&# 执行找到的脚本,其实里面就是厂商自己定义的编译选项
1043 unset f
envsetup.sh其主要作用如下:
  1. 加载了编译时使用到的函数命令,如:help,lunch,m,mm,mmm等
  2. 添加了两个编译选项:generic-eng和simulator,这两个选项是系统默认选项
  3.查找vendor/&-厂商目录&/和vendor/&厂商目录&/build/目录下的vendorsetup.sh,如果存在的话,加载执行它,添加厂商自己定义产品的编译选项
&其实,上述第3条是向编译系统添加了厂商自己定义产品的编译选项,里面的代码就是:add_lunch_comboxxx-xxx。
根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh最后,添加上add_lunch_combomyProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项
#mkdir vendor/farsight/
#touch vendor/farsight/vendorsetup.sh
#echo &add_lunch_combo fs100-eng& &vendor/farsight/vendorsetup.sh
这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息:
including vendor/farsight/vendorsetup.sh
2. 按照android官网的步骤,开始执行lunch full-eng
当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项
如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:
You're building on Linux
generic-eng simulator fs100-eng
Lunch menu... pick a combo:
&&&&1. generic-eng
&&&&2. simulator
&&&&3. fs100-eng
其中第3项是我们自己添加的编译项。
lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。
我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user,userdebug,分别表示:
eng: 工程机,
user:最终用户机
userdebug:调试测试机
tests:测试机
由此可见,除了eng和user外,另外两个一般不能交给最终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。
那么这四个类型是干什么用的呢?其实,在main.mk里有说明,在Android的源码里,每一个目标(也可以看成工程)目录都有一个Android.mk的makefile,每个目标的Android.mk中有一个类型声明:LOCAL_MODULE_TAGS,这个TAGS就是用来指定,当前的目标编译完了属于哪个分类里。
&&&PS:Android.mk和Linux里的makefile不太一样,它是Android编译系统自己定义的一个makefile来方便编译成:c,c++的动态、静态库或可执行程序,或java库或android的程序,
好了,我们来分析下lunch命令干了什么?
function lunch()
&&& localanswer
&&& if [ &$1& ]; then
&&&&&&# lunch后面直接带参数
&&&&&&&answer=$1
&&&&&&# lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择
&&&&&&&print_lunch_menu &
&&&&&&&echo -n &Which would you like? [generic-eng] &
&&&&&&&read answer
&&& localselection=
&&& if [ -z&$answer& ]
&&&&&&&&&&# 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng
&&&&&&&selection=generic-eng
&&& elif [&$answer& = &simulator& ]
&&&&&&&# 如果是模拟器
&&&&&&&selection=simulator
&&& elif (echo-n $answer | grep -q -e &^[0-9][0-9]*$&)
&&&&&&&# 如果answer是选择菜单的数字,则获取该数字对应的字符串
&&&&&&&if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
&&&&&&&then
&&&&&&&&&&&selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
&&&&&&&# 如果 answer字符串匹配 *-*模式(*的开头不能为-)
&&& elif (echo-n $answer | grep -q -e &^[^\-][^\-]*-[^\-][^\-]*$&)
&&&&&&&selection=$answer
&&& if [ -z&$selection& ]
&&&&&&&echo
&&&&&&&echo &Invalid lunch combo: $answer&
&&&&&&&return 1
&&& # specialcase the simulator
&&& if [&$selection& = &simulator& ]
&&&&&&&# 模拟器模式
&&&&&&&export TARGET_PRODUCT=sim
&&&&&&&export TARGET_BUILD_VARIANT=eng
&&&&&&&export TARGET_SIMULATOR=true
&&&&&&&export TARGET_BUILD_TYPE=debug
&&&&&&&# 将 product-variant模式中的product分离出来
&&&&&&&local product=$(echo -n $selection | sed -e &s/-.*$//&)
&&&&&&&# 检查之,调用关系check_product()-&get_build_var()-&build/core/config.mk比较罗嗦,不展开了
&&&&&&&check_product $product
&&&&&&&if [ $? -ne 0 ]
&&&&&&&then
&&&&&&&&&&&echo
&&&&&&&&&&&echo &** Don't have a product spec for: '$product'&
&&&&&&&&&&&echo &** Do you have the right repo manifest?&
&&&&&&&&&&&product=
&&&&&&&# 将 product-variant模式中的variant分离出来
&&&&&&&local variant=$(echo -n $selection | sed -e &s/^[^\-]*-//&)
&&&&&&&# 检查之,看看是否在 (user userdebug eng) 范围内
&&&&&&&check_variant $variant
&&&&&&&if [ $? -ne 0 ]
&&&&&&&then
&&&&&&&&&&&echo
&&&&&&&&&&&echo &** Invalid variant: '$variant'&
&&&&&&&&&&&echo &** Must be one of ${VARIANT_CHOICES[@]}&
&&&&&&&&&&&variant=
&&&&&&&if [ -z &$product& -o -z &$variant& ]
&&&&&&&then
&&&&&&&&&&&echo
&&&&&&&&&&&return 1
&#&导出环境变量,这里很重要,因为后面的编译系统都是依赖于这里定义的几个变量的
&&&&&&&export TARGET_PRODUCT=$product
&&&&&&&export TARGET_BUILD_VARIANT=$variant
&&&&&&&export TARGET_SIMULATOR=false
&&&&&&&export TARGET_BUILD_TYPE=release
&&& fi #!simulator
&&& #设置到环境变量,比较多,不再一一列出,最简单的方法 set &env.txt 可获得
&&&set_stuff_for_environment
&&& # 打印一些主要的变量,调用关系printconfig()-&get_build_var()-&build/core/config.mk-&build/core/envsetup.mk比较罗嗦,不展开了
&&&printconfig
由上面分析可知,lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以实际运行情况为例)
TARGET_PRODUCT=fs100
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
执行完上述两个步骤,就该执行:make命令了,下篇来分析。
.cn/s/blog_62ef2f1401013icb.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:9832次
排名:千里之外
原创:17篇
(1)(1)(3)(3)(1)(1)(2)(2)(1)(1)(1)(1)Android编译详解之lunch命令
segmentationfault作者:cheriecSegment fault
之所以能够流行于世,是与Glibc库中基本所有的函数都默认型参指针为非空有着密切关系的。
来自:http://oss./blog/article.php?uid_7/tid_700.html#comment
最近一段时间在linux下用C" />
Android编译详解之lunch命令
发布时间: 10:04:38
编辑:www.fx114.net
本篇文章主要介绍了"Android编译详解之lunch命令",主要涉及到Android编译详解之lunch命令方面的内容,对于Android编译详解之lunch命令感兴趣的同学可以参考一下。
写的非常不错Segment fault
之所以能够流行于世,是与Glibc库中基本所有的函数都默认型参指针为非空有着密切关系的。
来自:http://oss./blog/article.php?uid_7/tid_700.html#comment
最近一段时间在linux下用C做一些学习和开发,但是由于经验不足,问题多多。而段错误就是让我非常头痛的一个问题。不过,目前写一个一千行左右的代码,也很少出现段错误,或者是即使出现了,也很容易找出来,并且处理掉。
那什么是段错误?段错误为什么是个麻烦事?以及怎么发现程序中的段错误以及如何避免发生段错误呢?
一方面为了给自己的学习做个总结,另一方面由于至今没有找到一个比较全面介绍这个虽然是“FREQUENTLY ASKED
QUESTIONS”的问题,所以我来做个抛砖引玉吧。下面就从上面的几个问题出发来探讨一下“Segmentation
faults"吧。
1。什么是段错误?
2。为什么段错误这么“麻烦”?
3。编程中通常碰到段错误的地方有哪些?
4。如何发现程序中的段错误并处理掉?
1。什么是段错误?
下面是来自的定义:
segmentation fault (often shortened to segfault) is a particular
error condition that can occur during the operation of computer
software. In short, a segmentation fault occurs when a program
attempts to access a memory location that it is not allowed to
access, or attempts to access a memory location in a way that is
not allowed (e.g., attempts to write to a read-only location, or to
overwrite part of the operating system). Systems based on
processors like the Motorola 68000 tend to refer to these events as
Address or Bus errors.
Segmentation is one approach to memory management and protection in
the operating system. It has been superseded by paging for most
purposes, but much of the terminology of segmentation is still
used, "segmentation fault" being an example. Some operating systems
still have segmentation at some logical level although paging is
used as the main memory management policy.
On Unix-like operating systems, a process that accesses invalid
memory receives the SIGSEGV signal. On Microsoft Windows, a process
that accesses invalid memory receives the STATUS_ACCESS_VIOLATION
exception.
另外,这里有个基本上对照的中文解释,来自
所谓的段错误
就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,
后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中
就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访
问,cpu就会产生相应的异常保护,于是segmentation fault就出现了
通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的。
2。为什么段错误这么麻烦?
中国linux论坛有一篇精华帖子《Segment fault 之永远的痛》()
在主题帖子里头,作者这么写道:
写程序好多年了,Segment fault
是许多C程序员头疼的提示。指针是好东西,但是随着指针的使用却诞生了这个同样威力巨大的恶魔。
Segment fault 之所以能够流行于世,是与Glibc库中基本所有的函数都默认型参指针为非空有着密切关系的。
不知道什么时候才可以有能够处理NULL的glibc库诞生啊!
不得已,我现在为好多的函数做了衣服,避免glibc的函数被NULL给感染,导致我的Mem访问错误,而我还不知道NULL这个病毒已经在侵蚀我的身体了。
Segment fault 永远的痛......
后面有好多网友都跟帖了,讨论了Segmentation
faults为什么这么“痛”,尤其是对于服务器程序来说,是非常头痛的,为了提高效率,要尽量减少一些不必要的段错误的“判断和处理”,但是不检查又可能会存在段错误的隐患。
那么如何处理这个“麻烦”呢?
就像人不可能“完美”一样,由人创造的“计算机语言“同样没有“完美”的解决办法。
我们更好的解决办法也许是:
通过学习前人的经验和开发的工具,不断的尝试和研究,找出更恰当的方法来避免、发现并处理它。对于一些常见的地方,我们可以避免,对于一些“隐藏”的地方,我们要发现它,发现以后就要及时处理,避免留下隐患。
下面我们可以通过具体的实验来举出一些经常出现段错误的地方,然后再举例子来发现和找出这类错误藏身之处,最后处理掉。
3。编程中通常碰到段错误的地方有哪些?
为了进行下面的实验,我们需要准备两个工具,一个是gcc,一个是gdb
我是在ubuntu下做的实验,安装这两个东西是比较简单的
sudo apt-get install gcc-4.0 libc6-dev
sudo apt-get install gdb
好了,开始进入我们的实验,我们粗略的分一下类
1)往受到系统保护的内存地址写数据
有些内存是内核占用的或者是其他程序正在使用,为了保证系统正常工作,所以会受到系统的保护,而不能任意访问。
#i nclude &stdio.h&
&&&&&&& int i = 0;
&&&&&&& scanf ("%d", i);&
&&&&&&& printf ("%dn", i);
&&&&&&& return 0;
[Ctrl+A Select
编译和执行一下
$ gcc -o segerr segerr.c
$ ./segerr
咋一看,好像没有问题哦,不就是读取一个数据然后给输出来吗?
下面我们来调试一下,看看是什么原因?
$ gcc -g -o segerr
segerr.c&&
&--加-g选项查看调试信息
$ gdb ./segerr
&--用l(list)显示我们的源代码
#i nclude &stdio.h&
6&&&&&&&&&&&&&&
int i = 0;
8&&&&&&&&&&&&&&
scanf ("%d", i);&
9&&&&&&&&&&&&&&
printf ("%dn", i);
10&&&&&&&&&&&&&
(gdb) b 8&&
&--用b(break)设置断点
Breakpoint 1 at 0x80483b7: file segerr.c, line 8.
(gdb) p i&&
&--用p(print)打印变量i的值[看到没,这里i的值是0哦]
&--用r(run)运行,直到断点处
Starting program: /home/falcon/temp/segerr
Breakpoint 1, main () at segerr.c:8
8&&&&&&&&&&&&&&
scanf ("%d", i);& --[试图往地址0处写进一个值]
&--用n(next)执行下一步
Program received signal SIGSEGV, Segmentation fault.
0xb7e9a1ca in _IO_vfscanf () from
/lib/tls/i686/cmov/libc.so.6
&--在上面我们接收到了SIGSEGV,然后用c(continue)继续执行
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) quit&&
&--退出gdb
我们“不小心”把&i写成了i
而我们刚开始初始化了i为0,这样我们不是试图向内存地址0存放一个值吗?实际上很多情况下,你即使没有初始化为零,默认也可能是0,所以要特别注意。
可以通过man 7 signal查看SIGSEGV的信息。
$ man 7 signal | grep SEGV
Reformatting signal(7), please wait...
SIGSEGV&&&&&
Core&&& Invalid
memory reference
#i nclude &stdio.h&
&&&&&&& char *p;
&&&&&&& p = NULL;
&&&&&&& *p = 'x';
&&&&&&& printf("%c", *p);
&&&&&&& return 0;
[Ctrl+A Select
很容易发现,这个例子也是试图往内存地址0处写东西。
这里我们通过gdb来查看段错误所在的行
$ gcc -g -o segerr
$ gdb ./segerr
&--直接运行,我们看到抛出段错误以后,自动显示出了出现段错误的行,这就是一个找出段错误的方法
Starting program: /home/falcon/temp/segerr
Program received signal SIGSEGV, Segmentation fault.
0x in main () at segerr.c:10
10&&&&&&&&&&&&&
2)内存越界(数组越界,变量类型不一致等)
#i nclude &stdio.h&
&&&&&&& char test[1];
&&&&&&& printf("%c", test[]);
&&&&&&& return 0;
[Ctrl+A Select
这里是比较极端的例子,但是有时候可能是会出现的,是个明显的数组越界的问题
或者是这个地址是根本就不存在的
#i nclude &stdio.h&
&&&&&&& int b = 10;
&&&&&&& printf("%sn", b);
&&&&&&& return 0;
[Ctrl+A Select
我们试图把一个整数按照字符串的方式输出出去,这是什么问题呢?
由于还不熟悉调试动态链接库,所以
我只是找到了printf的源代码的这里
声明部分:
&& &int pos =0
,cnt_printed_chars =0 ,
  unsigned char *
%s格式控制部分:
  &&& chptr
=va_arg (ap ,unsigned char *);
  &&& i =0
  &&& while
(chptr [i ])
  &&& {...
  &&&&&&&
cnt_printed_chars ++;
  &&&&&&&
putchar (chptr [i ++]);
细看看,发现了这样一个问题,在打印字符串的时候,实际上是打印某个地址开始的所有字符,但是当你想把整数当字符串打印的时候,这个整数被当成了一个地
址,然后printf从这个地址开始去打印字符,直到某个位置上的值为。所以,如果这个整数代表的地址不存在或者不可访问,自然也是访问了不该访问的
内存——segmentation fault。
类似的,还有诸如:sprintf等的格式控制问题
比如,试图把char型或者是int的按照%s输出或存放起来,如:
#i nclude &stdio.h&
#i nclude &string.h&
char c='c';
char buf[100];
printf("%s", c);&& &&& &//试图把char型按照字符串格式输出,这里的字符会解释成整数,再解释成地址,所以原因同上面那个例子
printf("%s", i);&& &&& &&& &//试图把int型按照字符串输出
memset(buf, 0, 100);
sprintf(buf, "%s", c);&& &//试图把char型按照字符串格式转换
memset(buf, 0, 100);
sprintf(buf, "%s", i);&& //试图把int型按照字符串转换
[Ctrl+A Select
其实大概的原因都是一样的,就是段错误的定义。但是更多的容易出错的地方就要自己不断积累,不段发现,或者吸纳前人已经积累的经验,并且注意避免再次发生。
&1&定义了指针后记得初始化,在使用的时候记得判断是否为NULL
&2&在使用数组的时候是否被初始化,数组下标是否越界,数组元素是否存在等
&3&在变量处理的时候变量的格式控制是否合理等
再举一个比较不错的例子:
我在进行一个多线程编程的例子里头,定义了一个线程数组
#define THREAD_MAX_NUM
pthread_t thread[THREAD_MAX_NUM];
用pthread_create创建了各个线程,然后用pthread_join来等待线程的结束
开始我就直接等待,在创建线程都成功的时候,pthread_join能够顺利等待各个线程结束,但是一旦创建线程失败,那用pthread_join来
等待那个本不存在的线程时自然会存在访问不能访问的内存的情况,从而导致段错误的发生,后来,通过不断调试和思考,并且得到网络上资料的帮助,找到了上面
的原因和解决办法:
在创建线程之前,先初始化我们的线程数组,在等待线程的结束的时候,判断线程是否为我们的初始值
如果是的话,说明我们的线程并没有创建成功,所以就不能等拉。否则就会存在释放那些并不存在或者不可访问的内存空间。
上面给出了很常见的几种出现段错误的地方,这样在遇到它们的时候就容易避免拉。但是人有时候肯定也会有疏忽的,甚至可能还是会经常出现上面的问题或者其他常见的问题,所以对于一些大型一点的程序,如何跟踪并找到程序中的段错误位置就是需要掌握的一门技巧拉。
4。如何发现程序中的段错误?
有个网友对这个做了比较全面的总结,除了感谢他外,我把地址弄了过来。文章名字叫《段错误bug的调试》(),应该说是很全面的。
而我常用的调试方法有:
1)在程序内部的关键部位输出(printf)信息,那样可以跟踪 段错误 在代码中可能的位置
为了方便使用这种调试方法,可以用条件编译指令#ifdef
DEBUG和#endif把printf函数给包含起来,编译的时候加上-DDEBUG参数就可以查看调试信息。反之,不加上该参数进行调试就可以。
2)用gdb来调试,在运行到段错误的地方,会自动停下来并显示出错的行和行号
个应该是很常用的,如果需要用gdb调试,记得在编译的时候加上-g参数,用来显示调试信息,对于这个,网友在《段错误bug的调试》文章里创造性的使用
这样的方法,使得我们在执行程序的时候就可以动态扑获段错误可能出现的位置:通过扑获SIGSEGV信号来触发系统调用gdb来输出调试信息。如果加上上
面提到的条件编译,那我们就可以非常方便的进行段错误的调试拉。
3)还有一个catchsegv命令
通过查看帮助信息,可以看到
Catch segmentation faults in programs
这个东西就是用来扑获段错误的,它通过动态加载器(ld-linux.so)的预加载机制(PRELOAD)把一个事先写好的库(/lib/libSegFault.so)加载上,用于捕捉断错误的出错信息。
到这里,“初级总结篇”算是差不多完成拉。欢迎指出其中表达不当甚至错误的地方,先谢过!
参考资料[具体地址在上面的文章中都已经给出拉]:
1。段错误的定义
Definition of "Segmentation fault"
2。《什么是段错误》
3。《Segment fault 之永远的痛》
4。《段错误bug的调试》
虽然感觉没有写什么东西,但是包括查找资料和打字,也花了好些几个小时,不过总结一下也是值得的,欢迎和我一起交流和讨论,也欢迎对文章中表达不当甚至是错误的地方指正一下。
本文标题:
本页链接:

我要回帖

更多关于 编译安卓源码 lunch 的文章

 

随机推荐