Java代码引起的NATIVE野指针问题(下)

朴英敏,小米MIUI部门。从事嵌入式开发和调试工作8年多,擅长逆向分析方法,主要负责解决安卓系统稳定性问题。

实施hook:

我们有了hook,但目前还不知道是哪个so中释放了functor。

如果无法确定是哪个so,可以多hook几个so就行了。

当然对于特定的例子,也有技巧来确定so,比如我们这个例子:

被析构的对象是Functor类的对象,由于它的vtbl地址我们能够从log中获取到,

而vtbl一般指向定义了该类的so中,所以用vtbl值(0×73648de0)去map表中找,就能确定是哪个so了。


  1. ... 
  2.   73635000-73646000 rw-p 00000000 00:00 0 
  3.   73646000-73648000 r-xp 00000000 b3:18 1287       /system/lib/libwebviewchromium_plat_support.so 
  4. =>73648000-73649000 r--p 00001000 b3:18 1287       /system/lib/libwebviewchromium_plat_support.so  
  5.   73649000-7364a000 rw-p 00002000 b3:18 1287       /system/lib/libwebviewchromium_plat_support.so 
  6.   7364a000-73684000 rw-p 00000000 00:00 0 
  7.   73684000-73696000 r-xp 00000000 b3:18 1034       /system/lib/libjavacrypto.so 
  8.   73696000-73697000 r--p 00011000 b3:18 1034       /system/lib/libjavacrypto.so 
  9.   73697000-73698000 rw-p 00012000 b3:18 1034       /system/lib/libjavacrypto.so 
  10.   ... 

而需要注意的是,C++对象的释放是delete函数,

libwebviewchromium_plat_support.so不会直接调用libc的free函数,而是调用libc++.so中的delete函数,再由delete函数调用free函数,

所以我们得hook libc++.so的free函数,但打印调用栈的模块也依赖libc++.so,所以如果在hook函数中打印调用栈,也会遇到死循环问题。

所以我们得hook libwebviewchromium_plat_support.so中的delete函数,这样既减少log量,也能避免死循环。

先确认libwebviewchromium_plat_support.so是否依赖了delete函数:


  1. $ readelf -s libwebviewchromium_plat_support.so |grep UND 
  2.      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
  3.      1: 00000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_finalize 
  4.      2: 00000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit 
  5.      4: 00000000     0 FUNC    GLOBAL DEFAULT  UND __aeabi_unwind_cpp_pr0 
  6.      5: 00000000     0 FUNC    GLOBAL DEFAULT  UND __aeabi_unwind_cpp_pr1 
  7.      6: 00000000     0 FUNC    GLOBAL DEFAULT  UND getrlimit 
  8.      7: 00000000     0 FUNC    GLOBAL DEFAULT  UND setrlimit 
  9.      8: 00000000     0 FUNC    GLOBAL DEFAULT  UND __errno 
  10.      9: 00000000     0 FUNC    GLOBAL DEFAULT  UND strerror 
  11.     10: 00000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_print 
  12. =>  11: 00000000     0 FUNC    GLOBAL DEFAULT  UND _Znwj 
  13. =>  12: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv 
  14.     14: 00000000     0 FUNC    GLOBAL DEFAULT  UND __android_log_assert 
  15.     ... 
  16.     51: 00000000     0 FUNC    GLOBAL DEFAULT  UND __aeabi_llsr 
  17.     52: 00000000     0 OBJECT  GLOBAL DEFAULT  UND __popcount_tab 

其中11项_Znwj是new的符号,_ZdlPv是delete的符号。

接下来就用工具hook libwebviewchromium_plat_support.so的delete函数:


  1. extern void _ZdlPv(void *); 
  2. void inject__ZdlPv(void* ptr) { 
  3.     LOGD("delete %p",ptr); 
  4.     dumpNativeStack(); 
  5.     dumpJavaStack(); 
  6.     _ZdlPv(ptr); 

hook后复现问题,抓到的log如下:


  1. 10-27 21:19:52.961  8027  8027 D ObserverLayout: onStop: clz=com.miui.player.display.view.DisplayFragmentLayout{45665838 V.E..... ........ 0,0-1080,1920 #7f080039 app:id/content} 
  2. 10-27 21:19:52.965  8027  8027 I MusicBaseFragment: onDestroyView  the view is still attached, delay destroy 
  3. 10-27 21:19:52.966  8027  8027 D INJECT  : delete 0x7a7b8530 
  4. 10-27 21:19:52.986  8027  8027 D INJECT  : #00  pc 000015f6  /system/lib/libinject.so (inject__ZdlPv+21) 
  5. 10-27 21:19:52.986  8027  8027 D INJECT  : #01  pc 00001134  /system/lib/libwebviewchromium_plat_supp 
  6. 10-27 21:19:52.986  8027  8027 D INJECT  : #02  pc 00001088  /system/lib/libwebviewchromium_plat_supp 
  7. 10-27 21:19:52.987  8027  8027 D INJECT  : #03  pc 0001d30c  /system/lib/libdvm.so (dvmPlatformInvoke+112) 
  8. 10-27 21:19:52.987  8027  8027 D INJECT  : #04  pc 0004d8da  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JV+397) 
  9. 10-27 21:19:52.987  8027  8027 D INJECT  : #05  pc 00026720  /system/lib/libdvm.so 
  10. 10-27 21:19:52.987  8027  8027 D INJECT  : #06  pc 0002d790  /system/lib/libdvm.so (dvmMterpStd(Thread*)+76) 
  11. 10-27 21:19:52.987  8027  8027 D INJECT  : #07  pc 0002adf4  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JVa+184) 
  12. 10-27 21:19:52.988  8027  8027 D INJECT  : #08  pc 00060058  /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, +391) 
  13. 10-27 21:19:52.988  8027  8027 D INJECT  : #09  pc 00067ff6  /system/lib/libdvm.so 
  14. 10-27 21:19:52.988  8027  8027 D INJECT  : #10  pc 00026720  /system/lib/libdvm.so 
  15. 10-27 21:19:52.988  8027  8027 D INJECT  : #11  pc 0002d790  /system/lib/libdvm.so (dvmMterpStd(Thread*)+76) 
  16. 10-27 21:19:52.988  8027  8027 D INJECT  : #12  pc 0002adf4  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JVa+184) 
  17. 10-27 21:19:52.988  8027  8027 D INJECT  : #13  pc 0005fd74  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, O+335) 
  18. 10-27 21:19:52.988  8027  8027 D INJECT  : #14  pc 000494c2  /system/lib/libdvm.so 
  19. 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor.nativeDestroyGLFunctor(Native Method) 
  20. 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor.access$000(DrawGLFunctor.java:31) 
  21. 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor$DestroyRunnable.run(DrawGLFunctor.java:91) 
  22. 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.runCleanupTaskInternal(CleanupReference.java:159) 
  23. 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.access$300(CleanupReference.java:32) 
  24. 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference$LazyHolder$1.handleMessage(CleanupReference.java:93) 
  25. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.handleOnUiThread(CleanupReference.java:147) 
  26. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.cleanupNow(CleanupReference.java:141) 
  27. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor.destroy(DrawGLFunctor.java:46) 
  28. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.webview.chromium.WebViewChromium.destroy(WebViewChromium.java:430) 
  29. 10-27 21:19:52.990  8027  8027 D INJECT  :   at android.webkit.WebView.destroy(WebView.java:667) 
  30. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:64) 
  31. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:115) 
  32. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.miui.player.component.MusicBaseFragment.onDestroyView(MusicBaseFragment.java:216) 
  33. 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.Fragment.performDestroyView(Fragment.java:1898) 
  34. 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:954) 
  35. 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167) 
  36. 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:715) 
  37. 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1544) 
  38. 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl$3.run(FragmentManager.java:502) 
  39. 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1449) 
  40. 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443) 
  41. 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.os.Handler.handleCallback(Handler.java:733) 
  42. 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.os.Handler.dispatchMessage(Handler.java:95) 
  43. 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.os.Looper.loop(Looper.java:136) 
  44. 10-27 21:19:52.993  8027  8027 D INJECT  :   at android.app.ActivityThread.main(ActivityThread.java:5016) 
  45. 10-27 21:19:52.993  8027  8027 D INJECT  :   at java.lang.reflect.Method.invokeNative(Native Method) 
  46. 10-27 21:19:52.993  8027  8027 D INJECT  :   at java.lang.reflect.Method.invoke(Method.java:515) 
  47. 10-27 21:19:52.993  8027  8027 D INJECT  :   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 
  48. 10-27 21:19:52.993  8027  8027 D INJECT  :   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 
  49. 10-27 21:19:52.993  8027  8027 D INJECT  :   at dalvik.system.NativeStart.main(Native Method) 
  50. 10-27 21:19:53.020  8027  8027 I OpenGLRenderer: functor=0x7a7b8530,vtbl=0x400fc1b8 

从log中可以看到,确实是在distroy view的时候释放了Functor,而随后再Renderer中又使用了这个Functor。

打印崩溃时的java调用栈如下:


  1. 10-27 21:19:53.274  8027  8027 I dalvikvm: "main" prio=5 tid=1 TIMED_WAIT10-27 21:19:53.279  8027  8027 I dalvikvm:   | group="main" sCount=0 dsCount=0 obj=0x41716ca8 self=0x415344f8 
  2. 10-27 21:19:53.279  8027  8027 I dalvikvm:   | sysTid=6895 nice=-6 sched=0/0 cgrp=apps handle=1074409812 
  3. 10-27 21:19:53.280  8027  8027 I dalvikvm:   | state=R schedstat=( 0 0 0 ) utm=184 stm=61 core=3 
  4. 10-27 21:19:53.280  8027  8027 I dalvikvm:   at android.view.GLES20Canvas.nDrawDisplayList(Native Method) 
  5. 10-27 21:19:53.281  8027  8027 I dalvikvm:   at android.view.GLES20Canvas.drawDisplayList(GLES20Canvas.java:420) 
  6. 10-27 21:19:53.281  8027  8027 I dalvikvm:   at android.view.HardwareRenderer$GlRenderer.drawDisplayList(HardwareRenderer.java:1709) 
  7. 10-27 21:19:53.281  8027  8027 I dalvikvm:   at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1525) 
  8. 10-27 21:19:53.282  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.draw(ViewRootImpl.java:2475) 
  9. 10-27 21:19:53.282  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2347) 
  10. 10-27 21:19:53.283  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1977) 
  11. 10-27 21:19:53.284  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1094) 
  12. 10-27 21:19:53.285  8027  8027 I dalvikvm:   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5703) 
  13. 10-27 21:19:53.285  8027  8027 I dalvikvm:   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:764) 
  14. 10-27 21:19:53.286  8027  8027 I dalvikvm:   at android.view.Choreographer.doCallbacks(Choreographer.java:577) 
  15. 10-27 21:19:53.287  8027  8027 I dalvikvm:   at android.view.Choreographer.doFrame(Choreographer.java:547) 
  16. 10-27 21:19:53.288  8027  8027 I dalvikvm:   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:750) 
  17. 10-27 21:19:53.289  8027  8027 I dalvikvm:   at android.os.Handler.handleCallback(Handler.java:733) 
  18. 10-27 21:19:53.289  8027  8027 I dalvikvm:   at android.os.Handler.dispatchMessage(Handler.java:95) 
  19. 10-27 21:19:53.290  8027  8027 I dalvikvm:   at android.os.Looper.loop(Looper.java:136) 
  20. 10-27 21:19:53.291  8027  8027 I dalvikvm:   at android.app.ActivityThread.main(ActivityThread.java:5016) 
  21. 10-27 21:19:53.291  8027  8027 I dalvikvm:   at java.lang.reflect.Method.invokeNative(Native Method) 
  22. 10-27 21:19:53.292  8027  8027 I dalvikvm:   at java.lang.reflect.Method.invoke(Method.java:515) 
  23. 10-27 21:19:53.293  8027  8027 I dalvikvm:   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 
  24. 10-27 21:19:53.293  8027  8027 I dalvikvm:   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 
  25. 10-27 21:19:53.293  8027  8027 I dalvikvm:   at dalvik.system.NativeStart.main(Native Method) 

正常情况下,view在被destroy后不应该再被绘制,通过跟孙念沟通,得知这种情况可能是view在destroy前没有remove导致的。

分析代码:

上面delete时的调用栈中有特别的两行:


  1. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:64) 
  2. 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:115) 

这个是应用的代码,而这个问题只有在这个应用上出现过,所以很可能是应用的代码引起的,

所以查了下opengrok中的代码,发现有两处destroyHybridView()的实现:


  1. @v8-kk-pisces-alpha/packages/apps/MiuiMusic/common/music_sdk/hybrid/src/com/xiaomi/music/hybrid/HybridFragment.java 
  2.     private void destroyHybridView() { 
  3.         for (HybridView view : mHybridViews) { 
  4.             if (view != null) { 
  5.                 view.destroy(); 
  6.             } 
  7.         } 
  8.         mHybridViews.clear(); 
  9.     }  
  10.  
  11. @v8-kk-pisces-alpha/packages/apps/MiuiSdk/library/src/java/miui/hybrid/HybridFragment.java 
  12.     private void destroyHybridView() { 
  13.         for (HybridView view : mHybridViews) { 
  14.             if (view != null) { 
  15. =>              if (view.getParent() != null) { 
  16. =>                  ((ViewGroup) view.getParent()).removeView(view); 
  17. =>              } 
  18.                 view.destroy(); 
  19.             } 
  20.         } 
  21.         mHybridViews.clear(); 
  22.     } 

跟应用的同事沟通后得知,音乐应用是用上面的代码,也就是没有removeView的代码。

将上面代码中添加removeView的逻辑后不再复现问题。

虽然问题得到解决,但还不清楚为什么没有removeView会导致野指针。

为了找到根源仔细阅读了相关代码,发现代码中Render中有detachFunctor的代码:


  1. class GLES20Canvas extends HardwareCanvas { 
  2.     ... 
  3.     public void detachFunctor(int functor) { 
  4.         nDetachFunctor(mRenderer, functor); 
  5.     } 

用studio在这个代码中设置断点,得到如下调用栈:


  1. java.lang.Thread.State: RUNNABLE 
  2.       at android.view.GLES20Canvas.detachFunctor(GLES20Canvas.java:321) 
  3.       at android.view.HardwareRenderer$GlRenderer.detachFunctor(HardwareRenderer.java:1791) 
  4.       at android.view.ViewRootImpl.detachFunctor(ViewRootImpl.java:744) 
  5.       at com.android.webview.chromium.DrawGLFunctor$DestroyRunnable.detachNativeFunctor(DrawGLFunctor.java:97) 
  6.       at com.android.webview.chromium.DrawGLFunctor.detach(DrawGLFunctor.java:53) 
  7.       at com.android.webview.chromium.WebViewChromium.onDetachedFromWindow(WebViewChromium.java:1718) 
  8.       at android.webkit.WebView.onDetachedFromWindow(WebView.java:2108) 
  9.       at android.view.View.dispatchDetachedFromWindow(View.java:12631) 
  10.       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2587) 
  11.       at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3845) 
  12.       at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3818) 
  13.       at android.view.ViewGroup.removeView(ViewGroup.java:3750) 
  14.       at com.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:66) 
  15.       at com.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:119) 
  16.       at com.miui.player.component.MusicBaseFragment.onDestroyView(MusicBaseFragment.java:216) 
  17.       at android.app.Fragment.performDestroyView(Fragment.java:1898) 
  18.       at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:954) 
  19.       at android.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167) 
  20.       at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:715) 
  21.       at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1544) 
  22.       at android.app.FragmentManagerImpl$3.run(FragmentManager.java:502) 
  23.       at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1449) 
  24.       at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443) 
  25.       at android.os.Handler.handleCallback(Handler.java:733) 
  26.       at android.os.Handler.dispatchMessage(Handler.java:95) 
  27.       at android.os.Looper.loop(Looper.java:136) 
  28.       at android.app.ActivityThread.main(ActivityThread.java:5016) 
  29.       at java.lang.reflect.Method.invokeNative(Method.java:-1) 
  30.       at java.lang.reflect.Method.invoke(Method.java:515) 
  31.       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 
  32.       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 
  33.       at dalvik.system.NativeStart.main(NativeStart.java:-1) 

加了removeView后,会从Render中删除Functor,这样Render在绘制时,不再调用这个Functor。

这个问题只会在KK上有,L以后对Render做的很大改动,即使不做removeView,也不会存在野指针问题。

作者:朴英敏

来源:51CTO

时间: 2024-11-03 01:51:13

Java代码引起的NATIVE野指针问题(下)的相关文章

Java代码引起的NATIVE野指针问题(上)

朴英敏,小米MIUI部门.从事嵌入式开发和调试工作8年多,擅长逆向分析方法,主要负责解决安卓系统稳定性问题. 上周音乐组同事反馈了一个必现Native Crash问题,tombstone如下: pid: 5028, tid: 5028, name: com.miui.player  >>> com.miui.player <<<  signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 79801f28      r0

《Spring实战(第4版)》——2.3 通过Java代码装配bean

2.3 通过Java代码装配bean 尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化配置是更为推荐的方式,但有时候自动化配置的方案行不通,因此需要明确配置Spring.比如说,你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了. 在这种情况下,你必须要采用显式装配的方式.在进行显式配置的时候,有两种可选方案:Java和XML.在这节中,我们将会学习如何使用Java配置,

指针辨析:悬垂指针、哑指针、野指针、智能指针

悬垂指针:   1:提出的原因: 请看下面的代码片段: int *p=NULL; void main() { int i=10;p=&i; cout<<"第一次:*p = "<<*p<<endl; cout<<"第二次:*p = "<<*p<<endl; } int *p=NULL; void fun() {int i=10;p=&i;} void main() { fun();

从Java代码到Java堆

优化应用程序代码的内存使用并不是一个新主题,但是人们通常并没有很好地理解这个主题.本文将简要介绍 Java 进 程的内存使用,随后深入探讨您编写的 Java 代码的内存使用.最后,本文将展示提高代码内存效率的方法,特别强调了 HashMap 和 ArrayList 等 Java 集合的使用. 背景信息:Java 进程的内存使用 通过在命令行中执行 java 或者启动某种基于 Java 的中间件来运行 Java 应用程序时,Java 运行时会创建一个操作系统进程,就像您运行基于 C 的 程序时那样

使用非Java代码

JAVA语言及其标准API(应用程序编程接口)应付应用程序的编写已绰绰有余.但在某些情况下,还是必须使用非JAVA编码.例如,我们有时要访问操作系统的专用特性,与特殊的硬件设备打交道,重复使用现有的非Java接口,或者要使用"对时间敏感"的代码段,等等.与非Java代码的沟通要求获得编译器和"虚拟机"的专门支持,并需附加的工具将Java代码映射成非Java代码(也有一个简单方法:在第15章的"一个Web应用"小节中,有个例子解释了如何利用标准输入

内存陷阱:驯服C++中的野指针

什么是野指针? 一个母亲有两个小孩(两个指针),一个在厨房,一个在卧室,(属于不同的代码块,其生存期不同)母亲让在厨房的小孩带一块蛋糕(指针指向的对象)给在卧室的小孩,这样在卧室的孩子才肯写作业.但这个在厨房的小孩比较淘气,他在走出厨房时自己将蛋糕吃了,没能带出来.而在卧室的没有吃到蛋糕,所以不肯完成他的作业.结果母亲却不知道卧室的孩子没有吃到蛋糕,还以为作业完了.结果第二天她就被老师召唤到办公室了.事情麻烦了. 这样,那个在卧室的孩子就是野指针了,因为他没有得到应得的蛋糕,不能完成母亲交给他的

空指针(NULL,0),野指针,void*的讲解

一:野指针 "野指针"不是NULL指针,是指向"垃圾"内存的指针. "野指针"的成因主要有两种: (1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存.例如      char *p = NULL;      char *str = (char *) malloc(100); (2)指针p被free或者

基于C语言中野指针的深入解析

"野指针"不是NULL指针,是指向"垃圾"内存的指针.人们一般不会错用NULL指针,因为用if语句很容易判断.但是"野指针"是很危险的,if语句对它不起作用   "野指针"的成因主要有两种:(1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存.例如 复制代码 代码如下: char *

C语言之free函数以及野指针介绍

以下是对C语言中的free函数与野指针进行了详细的分析介绍,需要的朋友可以参考下   [FROM MSDN && 百科]原型:void free(void *ptr); #include<stdlib.h>或#include <malloc.h> Deallocate space in memory 释放ptr指向的存储空间.被释放的空间通常被送入可用存储区池,以后可在调用malloc.realloc以及realloc函数来再分配.注意:连续两次使用free函数,肯