我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java代码引起的NATIVE野指针问题怎么解决

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java代码引起的NATIVE野指针问题怎么解决

Java代码引起的NATIVE野指针问题怎么解决,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

实施hook:

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

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

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

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

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

...   73635000-73646000 rw-p 00000000 00:00 0   73646000-73648000 r-xp 00000000 b3:18 1287       /system/lib/libwebviewchromium_plat_support.so =>73648000-73649000 r--p 00001000 b3:18 1287       /system/lib/libwebviewchromium_plat_support.so    73649000-7364a000 rw-p 00002000 b3:18 1287       /system/lib/libwebviewchromium_plat_support.so   7364a000-73684000 rw-p 00000000 00:00 0   73684000-73696000 r-xp 00000000 b3:18 1034       /system/lib/libjavacrypto.so   73696000-73697000 r--p 00011000 b3:18 1034       /system/lib/libjavacrypto.so   73697000-73698000 rw-p 00012000 b3:18 1034       /system/lib/libjavacrypto.so   ...

而需要注意的是,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函数:

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

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

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

extern void _ZdlPv(void *); void inject__ZdlPv(void* ptr) {     LOGD("delete %p",ptr);     dumpNativeStack();     dumpJavaStack();     _ZdlPv(ptr); }

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

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} 10-27 21:19:52.965  8027  8027 I MusicBaseFragment: onDestroyView  the view is still attached, delay destroy 10-27 21:19:52.966  8027  8027 D INJECT  : delete 0x7a7b8530 10-27 21:19:52.986  8027  8027 D INJECT  : #00  pc 000015f6  /system/lib/libinject.so (inject__ZdlPv+21) 10-27 21:19:52.986  8027  8027 D INJECT  : #01  pc 00001134  /system/lib/libwebviewchromium_plat_supp 10-27 21:19:52.986  8027  8027 D INJECT  : #02  pc 00001088  /system/lib/libwebviewchromium_plat_supp 10-27 21:19:52.987  8027  8027 D INJECT  : #03  pc 0001d30c  /system/lib/libdvm.so (dvmPlatformInvoke+112) 10-27 21:19:52.987  8027  8027 D INJECT  : #04  pc 0004d8da  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JV+397) 10-27 21:19:52.987  8027  8027 D INJECT  : #05  pc 00026720  /system/lib/libdvm.so 10-27 21:19:52.987  8027  8027 D INJECT  : #06  pc 0002d790  /system/lib/libdvm.so (dvmMterpStd(Thread*)+76) 10-27 21:19:52.987  8027  8027 D INJECT  : #07  pc 0002adf4  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JVa+184) 10-27 21:19:52.988  8027  8027 D INJECT  : #08  pc 00060058  /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, +391) 10-27 21:19:52.988  8027  8027 D INJECT  : #09  pc 00067ff6  /system/lib/libdvm.so 10-27 21:19:52.988  8027  8027 D INJECT  : #10  pc 00026720  /system/lib/libdvm.so 10-27 21:19:52.988  8027  8027 D INJECT  : #11  pc 0002d790  /system/lib/libdvm.so (dvmMterpStd(Thread*)+76) 10-27 21:19:52.988  8027  8027 D INJECT  : #12  pc 0002adf4  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JVa+184) 10-27 21:19:52.988  8027  8027 D INJECT  : #13  pc 0005fd74  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, O+335) 10-27 21:19:52.988  8027  8027 D INJECT  : #14  pc 000494c2  /system/lib/libdvm.so 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor.nativeDestroyGLFunctor(Native Method) 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor.access$000(DrawGLFunctor.java:31) 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor$DestroyRunnable.run(DrawGLFunctor.java:91) 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.runCleanupTaskInternal(CleanupReference.java:159) 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.access$300(CleanupReference.java:32) 10-27 21:19:52.989  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference$LazyHolder$1.handleMessage(CleanupReference.java:93) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.handleOnUiThread(CleanupReference.java:147) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.org.chromium.content.common.CleanupReference.cleanupNow(CleanupReference.java:141) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.webview.chromium.DrawGLFunctor.destroy(DrawGLFunctor.java:46) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.android.webview.chromium.WebViewChromium.destroy(WebViewChromium.java:430) 10-27 21:19:52.990  8027  8027 D INJECT  :   at android.webkit.WebView.destroy(WebView.java:667) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:64) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:115) 10-27 21:19:52.990  8027  8027 D INJECT  :   at com.miui.player.component.MusicBaseFragment.onDestroyView(MusicBaseFragment.java:216) 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.Fragment.performDestroyView(Fragment.java:1898) 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:954) 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167) 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:715) 10-27 21:19:52.991  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1544) 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl$3.run(FragmentManager.java:502) 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1449) 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443) 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.os.Handler.handleCallback(Handler.java:733) 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.os.Handler.dispatchMessage(Handler.java:95) 10-27 21:19:52.992  8027  8027 D INJECT  :   at android.os.Looper.loop(Looper.java:136) 10-27 21:19:52.993  8027  8027 D INJECT  :   at android.app.ActivityThread.main(ActivityThread.java:5016) 10-27 21:19:52.993  8027  8027 D INJECT  :   at java.lang.reflect.Method.invokeNative(Native Method) 10-27 21:19:52.993  8027  8027 D INJECT  :   at java.lang.reflect.Method.invoke(Method.java:515) 10-27 21:19:52.993  8027  8027 D INJECT  :   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 10-27 21:19:52.993  8027  8027 D INJECT  :   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 10-27 21:19:52.993  8027  8027 D INJECT  :   at dalvik.system.NativeStart.main(Native Method) 10-27 21:19:53.020  8027  8027 I OpenGLRenderer: functor=0x7a7b8530,vtbl=0x400fc1b8

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

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

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 10-27 21:19:53.279  8027  8027 I dalvikvm:   | sysTid=6895 nice=-6 sched=0/0 cgrp=apps handle=1074409812 10-27 21:19:53.280  8027  8027 I dalvikvm:   | state=R schedstat=( 0 0 0 ) utm=184 stm=61 core=3 10-27 21:19:53.280  8027  8027 I dalvikvm:   at android.view.GLES20Canvas.nDrawDisplayList(Native Method) 10-27 21:19:53.281  8027  8027 I dalvikvm:   at android.view.GLES20Canvas.drawDisplayList(GLES20Canvas.java:420) 10-27 21:19:53.281  8027  8027 I dalvikvm:   at android.view.HardwareRenderer$GlRenderer.drawDisplayList(HardwareRenderer.java:1709) 10-27 21:19:53.281  8027  8027 I dalvikvm:   at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1525) 10-27 21:19:53.282  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.draw(ViewRootImpl.java:2475) 10-27 21:19:53.282  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2347) 10-27 21:19:53.283  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1977) 10-27 21:19:53.284  8027  8027 I dalvikvm:   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1094) 10-27 21:19:53.285  8027  8027 I dalvikvm:   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5703) 10-27 21:19:53.285  8027  8027 I dalvikvm:   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:764) 10-27 21:19:53.286  8027  8027 I dalvikvm:   at android.view.Choreographer.doCallbacks(Choreographer.java:577) 10-27 21:19:53.287  8027  8027 I dalvikvm:   at android.view.Choreographer.doFrame(Choreographer.java:547) 10-27 21:19:53.288  8027  8027 I dalvikvm:   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:750) 10-27 21:19:53.289  8027  8027 I dalvikvm:   at android.os.Handler.handleCallback(Handler.java:733) 10-27 21:19:53.289  8027  8027 I dalvikvm:   at android.os.Handler.dispatchMessage(Handler.java:95) 10-27 21:19:53.290  8027  8027 I dalvikvm:   at android.os.Looper.loop(Looper.java:136) 10-27 21:19:53.291  8027  8027 I dalvikvm:   at android.app.ActivityThread.main(ActivityThread.java:5016) 10-27 21:19:53.291  8027  8027 I dalvikvm:   at java.lang.reflect.Method.invokeNative(Native Method) 10-27 21:19:53.292  8027  8027 I dalvikvm:   at java.lang.reflect.Method.invoke(Method.java:515) 10-27 21:19:53.293  8027  8027 I dalvikvm:   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 10-27 21:19:53.293  8027  8027 I dalvikvm:   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 10-27 21:19:53.293  8027  8027 I dalvikvm:   at dalvik.system.NativeStart.main(Native Method)

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

分析代码:

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

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

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

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

@v8-kk-pisces-alpha/packages/apps/MiuiMusic/common/music_sdk/hybrid/class="lazy" data-src/com/xiaomi/music/hybrid/HybridFragment.java     private void destroyHybridView() {         for (HybridView view : mHybridViews) {             if (view != null) {                 view.destroy();             }         }         mHybridViews.clear();     }   @v8-kk-pisces-alpha/packages/apps/MiuiSdk/library/class="lazy" data-src/java/miui/hybrid/HybridFragment.java     private void destroyHybridView() {         for (HybridView view : mHybridViews) {             if (view != null) { =>              if (view.getParent() != null) { =>                  ((ViewGroup) view.getParent()).removeView(view); =>              }                 view.destroy();             }         }         mHybridViews.clear();     }

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

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

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

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

class GLES20Canvas extends HardwareCanvas {     ...     public void detachFunctor(int functor) {         nDetachFunctor(mRenderer, functor);     }

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

java.lang.Thread.State: RUNNABLE       at android.view.GLES20Canvas.detachFunctor(GLES20Canvas.java:321)       at android.view.HardwareRenderer$GlRenderer.detachFunctor(HardwareRenderer.java:1791)       at android.view.ViewRootImpl.detachFunctor(ViewRootImpl.java:744)       at com.android.webview.chromium.DrawGLFunctor$DestroyRunnable.detachNativeFunctor(DrawGLFunctor.java:97)       at com.android.webview.chromium.DrawGLFunctor.detach(DrawGLFunctor.java:53)       at com.android.webview.chromium.WebViewChromium.onDetachedFromWindow(WebViewChromium.java:1718)       at android.webkit.WebView.onDetachedFromWindow(WebView.java:2108)       at android.view.View.dispatchDetachedFromWindow(View.java:12631)       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2587)       at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3845)       at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3818)       at android.view.ViewGroup.removeView(ViewGroup.java:3750)       at com.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:66)       at com.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:119)       at com.miui.player.component.MusicBaseFragment.onDestroyView(MusicBaseFragment.java:216)       at android.app.Fragment.performDestroyView(Fragment.java:1898)       at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:954)       at android.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167)       at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:715)       at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1544)       at android.app.FragmentManagerImpl$3.run(FragmentManager.java:502)       at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1449)       at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)       at android.os.Handler.handleCallback(Handler.java:733)       at android.os.Handler.dispatchMessage(Handler.java:95)       at android.os.Looper.loop(Looper.java:136)       at android.app.ActivityThread.main(ActivityThread.java:5016)       at java.lang.reflect.Method.invokeNative(Method.java:-1)       at java.lang.reflect.Method.invoke(Method.java:515)       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)       at dalvik.system.NativeStart.main(NativeStart.java:-1)

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

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

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java代码引起的NATIVE野指针问题怎么解决

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java代码引起的NATIVE野指针问题怎么解决

Java代码引起的NATIVE野指针问题怎么解决,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实施hook:我们有了hook,但目前还不知道是哪个so中释放了f
2023-06-17

sql模式设置引起的问题怎么解决

今天小编给大家分享一下sql模式设置引起的问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1 报错类似如下数据库错
2023-06-30

c语言strcpy引起的缓冲区溢出问题怎么解决

解决strcpy引起的缓冲区溢出问题可以采取以下几种方法:使用更安全的函数:可以使用strncpy函数来替代strcpy函数,strncpy函数会限制复制的长度,避免溢出。手动检查字符串长度:在使用strcpy函数复制字符串之前,可以手动检
c语言strcpy引起的缓冲区溢出问题怎么解决
2024-03-02

JAVA中的Unicode编码问题怎么解决

在Java中解决Unicode编码问题有多种方法:1. 使用正确的字符编码读取和写入文件:当从文件中读取或写入文本时,需要注意使用正确的字符编码。常见的字符编码包括UTF-8、UTF-16等。例如,在读取文件时,可以使用InputStrea
2023-08-19

numpy数组拷贝地址所引起的同步替换问题怎么解决

今天小编给大家分享一下numpy数组拷贝地址所引起的同步替换问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。问题出
2023-07-05

Java电话号码的字母组合问题怎么解决

这篇文章主要介绍了Java电话号码的字母组合问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java电话号码的字母组合问题怎么解决文章都会有所收获,下面我们一起来看看吧。电话号码的字母组合中等给定一个
2023-07-05

JUC中的Lock锁与synchronized同步代码块问题怎么解决

这篇文章主要介绍“JUC中的Lock锁与synchronized同步代码块问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JUC中的Lock锁与synchronized同步代码块问题怎么解
2023-06-29

JS怎么解决Array.fill()参数为对象指向同一个引用地址的问题

本篇内容介绍了“JS怎么解决Array.fill()参数为对象指向同一个引用地址的问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!JS解决
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录