log比较大小方法:log1/48/7与log1/56/5

比较Log3.4^0.7与log0.6^0.8与(1/3)^-1/2的大小_百度作业帮 拍照搜题,秒出答案 比较Log3.4^0.7与log0.6^0.8与(1/3)^-1/2的大小 比较Log3.4^0.7与log0.6^0.8与(1/3)^-1/2的大小 10^(Log3.4^0.7)=3.4^0.7>110^(log0.6^0.8)=0.6^0.8<110^((1/3)^-1/2)=10^(3^0.5)>10^0.7>3.4^0.7=10^(Log3.4^0.7)所以,10^((1/3)^-1/2)>10^(Log3.4^0.7)>10^(log0.6^0.8)(1/3)^-1/2>Log3.4^0.7>log0.6^0.8(1/2)0.1次方和(1/2)0.2次方.比较大小!log‘3’2和log‘3‘5.比较大小.(‘3’为底数)_百度作业帮 拍照搜题,秒出答案 (1/2)0.1次方和(1/2)0.2次方.比较大小!log‘3’2和log‘3‘5.比较大小.(‘3’为底数) (1/2)0.1次方和(1/2)0.2次方.比较大小!log‘3’2和log‘3‘5.比较大小.(‘3’为底数) 1.因为﹙﹚在定义域R上单调递减,且0.1<0.2,所以﹙﹚0.1次方>﹙﹚0.2次方 2.因为㏒x在定义域﹙0,+∞)上单调递增,且2<5,所以㏒2<㏒5 (1/2)^0.1=(1/2)^1/10=1/2开10次方; (1/2)^0.2次方=(1/2)^1/5=1/2开5次方。 所以,(1/2)0.2次方大于 (1/2)0.1次方。 因为底数相同,因此,log‘3‘5大于log‘3’2Android&Native/Tombstone&Crash&Log&详细分析[原创] Android 虽然已经有好几年了,但是NDK的开放速度却非常缓慢,所以目前网络上针对对Android Native Crash的分析说明还比较少,尤其是非常详细的分析方式更难以查询。因此大部分程序员在遇到难以进行addr2line的crash log时,会一筹莫展。事实上这份log中的其他部分同样提供了非常丰富的信息可供解读,所以在这里总结一下对在这方面的一些经验,在这里以Android samples中的hello-jni为参照做了一定的修改产生的crash来进行分析说明。在深入理解错误日志的分析之后,许多难以复制或者几乎不能重现的bug也能够得到有效的解决。以下所有内容为夜莺原创。 内容主要分为一下几个部分: 1.Library Symbols (共享库的符号) 2.Analyze Tools (可用到的分析工具) 3.CrashLog & Header& 4.CrashLog&& Backtrace(For most crashes) 5.CrashLog&& Registers 6.CrashLog&& Memory 7.CrashLog&& Stack 8.Library Base Address (共享库在内存中基地址) 1.Library Symbols (共享库的符号) ndk提供了一些工具可以供程序员直接获取到出错的文件,函数以及行数。 但是这部分工具都需要没有去符号的共享库(通常是放在out/target/product/xxx/symbols/system/lib)。而out/target/product/xxx/system/lib中的共享库是去掉了符号的,所以直接从设备上抓下来的lib是不能够通过工具来找到对应的符号(而且没有去symbol的库比去掉的空间占用会大许多)。所以如果想要分析一份native crash,那么unstripped lib几乎不可缺少,但是即使是strip过的库也同样会包含少量的symbol。 2.Analyze Tools& 即常用的辅助工具 01&addr2line &($(ANDROID_NDK)\toolchains\arm-linux-androideabi-4.7\prebuilt\windows\bin) 02&#通过backtrace一栏提供的地址查询对应的符号,可以定位到文件,函数,行数. addr2line &aCfe libs $(trace_address) 05&ndk-stack (android-ndk-r8d\ndk-stack) 06&#相当于执行多次addr2line, 可以直接针对一份crash log使用,会输出所有backtrace里地址对应的symbol ndk-stack &sym $(lib_directory) &dump $(crash_log_file) 09&objdump (android-ndk-r8d\toolchains\arm-linux-androideabi-4.7\prebuilt\windows\bin) 10&#Dump the object file. 通过汇编代码定位错误的原因,大部分复杂的问题可以通过这种方式得到解决。 objdump -S $(objfile) & $(output_file) 3.Crash Log - Header 信息头,包含当前系统版本有关的信息,如果是做平台级的开发,这将有助于定位当前的系统的开发版本。 description: xxxx 4&Hardware: 5&Revision: 6&Bootloader: Linux version 3.4.5 xxxx 这部分较为容易阅读。所以不再赘述。 4.CrashLog&& Backtrace(For most crashes) 即最常用的看backtrace部分,backtrace的地址可用addr2line或者ndk-stack查找对应的symbol,非常直观,大多数的crash都能够通过这种方式解决。 01&backtrace: &pc 00026fbc &/system/lib/libc.so &pc 000004cf &/data/app-lib/com.example.hellojni-1/libhello-jni.so (Java_com_example_hellojni_HelloJni_stringFromJNI+18) &/system/lib/libdvm.so (dvmPlatformInvoke+112) &/system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+500) &/system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+200) &/system/lib/libdvm.so &/system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180) &pc 0006175f &/system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374) &/system/lib/libdvm.so &/system/lib/libdvm.so &/system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180) &/system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272) &pc 0004a2ed &/system/lib/libdvm.so &/system/lib/libandroid_runtime.so &/system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+536) &pc 00000db7 &/system/bin/app_process &pc 00020ea0 &/system/lib/libc.so (__libc_init+64) &pc 00000ae8 &/system/bin/app_process 从上面这份backtrace可以看到包含一个pc地址和后面的symbol。部分错误可以通过只看这里的symbol发现问题所在。而如果想要更准确的定位,则需要借助ndk工具。 1&$addr2line -aCfe out/target/production/xxx/symbols/system/lib/libhello-jni.so 3&java_com_example_hellojni_HelloJni_stringFromJNI 4&/ANDROID_PRODUCT/hello-jni/jni/hello-jni.c:48 然后再来看看hello-jni.c 17&#include 18&#include func_a(char *p); func_b(char *p); func_a(char *p) & &const char* A = "AAAAAAAAA"; & &char* a = "dead"; & &memcpy(p, A, strlen(A)); & &memcpy(p, a, strlen(a)); & &p[strlen(a)] = 0; & &func_b(p); func_b(char *p) & &char* b = 0xddeeaadd; & &memcpy(b, p, strlen(p)); 43&jstring 44&Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, &jobject thiz ) & &char buf[10]; & &func_a(buf); & &return (*env)-&NewStringUTF(env, "Hello from JNI 可以看到现在只能看到出错在func_a(). 这里面有个比较特别的地方是为什么backtrace 中只有func_a而没有出现func_b. 这是编译器的处理部分,不过多赘述。所以现在只能从backtrace中确认#1是在func_a,然后#0是在libc中的某个函数死掉。其实symbols/system/lib中也包含有libc.so,可以通过addr2line确认是那个函数。而这里调用到libc的只有memcpy, 所以可以基本确定出错在memcpy,但是有三个memcpy,又怎么确定是哪一个呢?(当然,可以通过直接检查代码发现是在func_b里面) 5.CrashLog&& 寄存器信息,可以通过这部分信息基本确定系统为什么会错。 4000, tid: 4000, name: xample.hellojni & 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr &r0 ddeeaadd &r1 beab238c &r5 40e1b760 &r8 beab23a8 &r9 4bdd2c98 &sl 40e1d050 &fp &sp beab2380 &lr &pc 400dffbc &cpsr &6e6a6f6c6c656865 &726f6c6f632f3c64 &3e2d2d206f646f54 &d5 &656d616e20726f6c &d7 & &d10 0000 & &d12 0000 & &d14 0000 & &d16 019e & &d18 0000 &d19 000000 & &d20 e000 & &d22 0000 &d23 090a0b0c0d0e0f10 & &d24 0003d &d25 000000 & &d26 0000b7 & &d28 0003d & &d30 0001 这部分信息展示了出错时的运行状态, 当前中断原因是收到SIGSEGV(通常crash也都是因为收到这个信号,也有少数是因为SIGFPE,即除0操作)。错误码是SEGV_MAPERR,常见的段错误。然后出错地址为ddeeaadd。即第39行的地址0xddeeadd。所以已经可以基本确定和指针b有关。 而代码里面接下来便是memcpy的操作。所以很明显就是在这里的memcpy有问题。 再看r0是ddeeaadd,r1是beab238c,r2是4,其实这三个寄存器刚好代表memcpy的操作参数。目的地址为ddeeaadd,源地址加偏移为beab238c,长度是4。这里有提到beab238c为源地址加偏移,原因的话会在后面解释。 通常我们需要关注的寄存器主要就是r0到pc,下面的32个寄存器的话通常是数据存取时常用,有时也会有重要信息,但一般情况下不会太关注。如果是对这部分不太了解的话,也不用担心,多看一看就自然明白了,笔者在尝试却解读之前也完全没有接触过这方面的内容。 6.CrashLog&& Memory 日志当中也提供了出错时寄存器地址里面的临近内存信息,信息量同样很丰富。之前有提到r1是与源地址有关,所以先看看r1(0xbeab238c)附近的内存情况 & &beab236c 4f659a18 df0027ad & & &beab237c & &beab238c 14641 & &beab239c 4c11cb40 40e1d040 40a2f614 4bdd2c94 & & &beab23ac 14608 & &beab23bc 40a5f019 4bdd2c94 beab238c在第四行,但是注意在第三行末尾有一串类似ASCII的字符,,这即是dead,而从这里开始,一段内存为 &14641即"64,65,61,64, 00,41,41,41, 41"647141。其实不难发现这就是dead'\0'AAAA,其后位于栈上的值没有初始化,会比较随机。 所以func_b中p的起始地址应该是从 的位置开始的,至于为什么r1是beab238c,解读一下汇编代码即可很容易发现。 在Android中使用的binoc实现中,查找源文件为memcpy.s(可通过addr2line 找到文件路径和行数)。看到出错点在memcpy.s +248。 这部分源码如下: 这两段的大致意思为从r1地址读取4个字节放到d0~d3,r1地址增加,然后将d0~d3中的数据存入到r0的地址去,同时r0也增加。 现在可以回过去查看d0~d3寄存器的最后一个字节,分别是64,65,61,64。为“dead“。因此当前的r1是增加后后的地址。而此时企图对r0处无效的地址0xddeeaadd写入数据,所以出错。并显示错误地址为0xddeeaadd. objdump,到这里,再提一提objdump的部分。 可以对共享库(.so)使用或者对目标文件(.o)使用,如果共享库比较大,那还是对被编译文件的目标文件使用比较好。通常来说Android的编译会默认保存目标文件,存放在out/target/product/xxxx/obj目录下面,于是现在找到libhello-jni.o通过objdump来查看它的信息。 Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, &jobject thiz ) &r4, [r4, #0] &r1, [r4, #0] &r1, [sp, #12] & &char buf[10]; & &func_a(buf); &f7ff fffe & &&/span&Java_com_example_hellojni_HelloJni_stringFromJNI& & &return (*env)-&NewStringUTF(env, "Hello from JNI &r0, [r5, #0] &r1, [pc, #28] & &; (38 &&/span&Java_com_example_hellojni_HelloJni_stringFromJNI+0x38&) &f8d0 229c & &r2, [r0, #668] & 不要太在意诸如'Java_com_example_hellojni_HelloJni_stringFromJNI','{','}'之类的符号,它只是提供给我们大致的位置信息,并不是完全等同于C语言中的代码段。 之前有通过backtrace #1看到(Java_com_example_hellojni_HelloJni_stringFromJNI+18)这样的信息,将+18转换成16进制为0x12.那么对应dump 出来的文件位置就是上面的12.指令为bl 0.这是一个常见的跳转指令。从源代码里面也可以看到开始调用func_a(). 再看看func_b的代码: func_b(char *p) &f7ff fffe & &&/span&strlen& &r0, [pc, #8] & &; (18 &&/span&func_b+0x18&) &e8bd 4010 & & ldmia.w & &sp!, {r4, lr} &f7ff bffe & &&/span&memcpy& &ddeeaadd & &0xddeeaadd 先将r0(p指针的值)放入r4,调用strlen,返回值默认放入r0(值为4),再将r4取出放入r1,然后从pc+8的位置拿地址放入r0(可以看到func_b+0x18为0xddeeaadd),再跳转到memcpy。所以r0为ddeeaadd,r1为p指针的值,r4为长度。由此进行了memcpy的调用,然后出错。 通过objdump通常可以更进一步的确定错误产生的情况,对追踪代码逻辑有极大的帮助,所以在很多情况下解决问题可以只通过阅读代码,并不需要不停地加debug打印并尝试去复制它。 7.CrashLog&& Stack 当backtrace信息量极少时(没有给全函数调用栈),这是重点。 Stack一栏提供的是线程调用栈的信息。可以从右边的一些symbol大致猜测出错的位置。但由于stack上的内容可能残留未初始化或者未清空的信息,又或者存储有其他的数据,所以有时会造成一定的困惑。因此stack上的symbol虽然大部分是本次调用栈的symbol,但不一定全都是。 & beab2340 &4012ac68 & beab2344 & & beab2348 &4f659a50 & beab234c &0000002f & beab2350 & & beab2354 & & beab2358 &beab2390 & beab235c &4012ac68 & beab2360 & & beab2364 &400cb528 &/system/lib/libc.so & beab2368 & & beab236c &4f659a18 & beab2370 & &/data/app-lib/com.example.hellojni-1/libhello-jni.so & beab2374 & &/data/app-lib/com.example.hellojni-1/libhello-jni.so (func_a+56) & beab2378 &df0027ad & beab237c & &beab2380 &ddeeaadd & beab2384 & &/data/app-lib/com.example.hellojni-1/libhello-jni.so (Java_com_example_hellojni_HelloJni_stringFromJNI+22) 栈是由下往上(frame#02--�)。 现在可以大致看到从#01到#00,从Java_com_example_hellojni_HelloJni_stringFromJNI进入func_a。但是这里是不能够通过左边的地址直接addr2line得到目标symbol。它是属于在内存当中的相对地址。接下来就会提到如何去通过相对地址计算可用的addr2line地址。 8.Library Base Address (共享库在内存中基地址) 通过地址计算得出可用的addr2line地址。 addr2line需要一份未去symbol的共享库。当代码没有改变时,每次生成的.so的符号位置应该是相同的。所以如果想要得到有效的符号,必须要使用程序运行时对应的未去符号的.so。 jni在运行时可以看到在java中有load_library的动作,这个动作大致可以看做将一个库文件加载到内存当中。因此这个库在内存当中就存在一个加载的基地址,但是根据内存的情况和相应的算法,基地址每次都可能会不一样。addr2line需要的地址是相对于共享库的一个绝对地址。因此现在只要能够得到共享库在内存中的基地址就能够有办法通过stack上的地址计算出可用的addr2line地址。 在上面的stack和backtrace信息当中有(Java_com_example_hellojni_HelloJni_stringFromJNI+22)和(Java_com_example_hellojni_HelloJni_stringFromJNI+18)这两个symbol的相对地址和绝对地址。 所以基地址的计算应该为对应的地址相减:0x - 0x000004cf - 0x4 = 为了验证基地址有效性,可以尝试计算0x(func_a+56)的符号:0x -&0x = 0x4a5。 然后使用addr2line查询0x4a5得到hello-jni.c:34。 除此之外还有另一种方法计算可用的地址,同样需要stack里提供的个别的symbol信息: 例0x(func_a+56),然后之前有提到objdump可以直接将.so作为输入,这时会出来整个lib的汇编信息。然后可以从中找到"0xxxxxxxx&<func_a>:"这样的信息,前面的0xxxxxx就代表函数的在lib中的地址,在这里是"0x46c&<func_a>:" ,然后加上0x38(56) 就等于0x4a4,这个和之前有一定的差别,原因是stack上保存的会是函数返回地址,但指向的指令是相同的。 提出基地址的问题是为了进一步说明stack中的地址和backtrace中地址的不同,以及共享库被加载到内存当中指令的存在形式,但是通过比较也可以发现,在所加载的库非常大的时候(例如100M+)前一种方式得到可以用的地址会相对于后一种方式简单许多。 大多数情况下应该是不需要使用计算基地址的方式。但是也有个别的日志信息给出的backtrace不完整,导致难以解析出具体的问题所在。这个时候就需要使用基地址计算的方式得出可用的addr2line地址。 到最后看来,一般只要有一份类似于错误日志的信息文件,通常可以解决绝大部分的问题。那么如果是运行时,可以通过gdb(如果打开corefile的选项更好),或者kill -9(同样需要打开编译选项才行)。还有就是Android系统通常内自带有debuggerd命令可以使用。详情可以从上网查阅。 最后附上本次测试的源码:/s/yVmhF5M5tTuIi 我的更多文章: ( 17:44:37)( 17:33:56)( 18:49:29)( 18:55:50)( 12:40:39) 已投稿到: 以上网友发言只代表其个人观点,不代表新浪网的观点或立场。比较大小:log以1/4为底8/7的对数与log以1/5为底6/5的对数_百度作业帮 拍照搜题,秒出答案 比较大小:log以1/4为底8/7的对数与log以1/5为底6/5的对数 比较大小:log以1/4为底8/7的对数与log以1/5为底6/5的对数 作图,可以知道.log以1/4为底8/7大&作图课本上有说明如何比较log5 6和log7 8的大小比较以5为底6的对数和以7为底8的对数的大小_百度作业帮 拍照搜题,秒出答案 如何比较log5 6和log7 8的大小比较以5为底6的对数和以7为底8的对数的大小 如何比较log5 6和log7 8的大小比较以5为底6的对数和以7为底8的对数的大小 如何比较log₅6和log₇8的大小log₅6=log&#×5)=log₅5+log&#=1+log&#;log₇8=log&#×7)=log₇7+log&#=1+log&#;由于log&#>log&#>log&#;(当两个对数的底数都大于1时:真数相同时,底大则对数小;底数相同时,真数大的对数也大.)∴log₅6>log₇8. 令y=㏒(x)(x+1)=ln(x+1)/lnx,∴ylnx=ln(x+1),∴y′lnx+y/x=1/(x+1),∴y′lnx=1/(x+1)-y/x=1/(x+1)-ln(x+1)/(xlnx),∴y′=[1/(lnx)^2][lnx/(x+1)-ln(x+1)/x]=[1/(lnx)^2][(xlnx-(x+1)ln(x+1)]/[x(x+1)]log6(7)>log7(8)即:log5(6)>log7(8) 祝开心!希望能帮到你~~}

我要回帖

更多关于 log4net 文件大小 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信