Umdhtools.exe: 如何使用 umdh.exe 来查找内存泄漏

http://support.microsoft.com/kb/268343

用户模式转储堆 (UMDH) 实用程序处理分析 Windows 堆分配特定进程的操作系统。主要针对此实用程序,并与之关联的其他工具用于 Windows 2000 和 Windows XP。单击 播放 按钮以查看此流媒体演示。

请注意 ACELP ® 编解码器编码视频,您需要安装在可用的免费 ACELP ® 编解码器 http://www.acelp.net/acelp_eval.php (http://www.acelp.net/acelp_eval.php)



<<The embedded streaming media event requires Microsoft Windows Media Player to view.>>


If you have problems viewing this video, click here.

请注意 因为 malloc C 运行时 (CRT) 模块中的函数使用的 Windows Server 2003 的原始发行版的框架指针省略 (FPO),您可能无法看到完整的堆栈信息 malloc 通过使用 UMDH 工具的函数。此问题已经在 Windows 2003 Service Pack 1 (SP1) 的 CRT 模块中。因此,您可以看到 Windows Server 2003 SP1 中的 malloc 函数的完整堆栈的信息。

更多信息
之前,使用 UMDH 如果您认为您会遇到内存泄漏,则应注意内存泄漏也可能是它们似乎是。您可能会发现,内存泄漏不是真正的内存泄漏,但更改增强了性能。对于示例中,M...

之前,使用 UMDH

如果您认为您会遇到内存泄漏,则应注意内存泄漏也可能是它们似乎是。您可能会发现,内存泄漏不是真正的内存泄漏,但更改增强了性能。对于示例中,Microsoft Jet 数据库引擎会消耗大量的内存(最多 256 MB 的计算机上的 128 MB) 因为检索数据,并将写入缓存。高速缓存允许以获得快速预读和写预 Jet 引擎缓冲。

若要确定遇到一个进程内存泄漏,使用 Windows 性能监视器 (Perfmon.exe) 和监视专用在您的应用程序的进程类别下的字节数。专用字节是总内存分配之后,该过程,但未与其他共享处理。请注意这是不同于虚拟字节,这也是有趣的监视。虚拟字节为单位) 是当前大小 (以字节为单位)该过程使用的虚拟地址空间。应用程序可以泄漏虚拟内存,但可能看不到专用字节分配的差异。如果您看不到内存时监视专用字节,但又增加怀疑您仍在运行的内存,以查看监视器虚拟字节不足如果您正在使用的虚拟内存设置。有关检测内存泄漏和 Windows 性能监视器 (Perfmon.exe) 的概述的其他信息,请访问下面的 Microsoft 网站:
http://msdn.microsoft.com/en-us/library/ms404355.aspx (http://msdn.microsoft.com/en-us/library/ms404355.aspx)
若要确保您的应用程序正在泄漏内存,请将怀疑与多个小版本,一个循环中的代码,然后监视 $ 专用和对于任何增加的内存的虚拟字节。监视以确保数专用字节和虚拟字节数不会不最终将保持相同,数字停止增加。如果没有内存会停止点不断增加,(例如,它不会不继续无限期地顺) 执行操作不会看到一个内存泄漏漏洞,但更有可能,您看到的增长缓存其最大大小。

如果您确定可以看出,内存泄漏之前使用 UMDH,请按照下列步骤操作:
  1. 安装的 UMDH 实用程序。
  2. 设置要包含系统 PATH 环境变量UMDH 的安装位置的文件夹。
  3. 将 _NT_SYMBOL_PATH 环境变量设置为Microsoft 符号服务器路径,以便 UMDH 可以找到调试符号文件。
UMDH 实用程序是附带的调试工具Windows 产品在下面的 Microsoft 网站:
http://www.microsoft.com/whdc/devtools/ddk/default.mspx (http://www.microsoft.com/whdc/devtools/ddk/default.mspx)
下载并安装该应用工具,然后将路径的系统设置环境变量,以在安装调试工具的路径。

在使用 UMDH 之前,您必须安装正确的调试符号您的应用程序和操作系统的组成部分。使用 Microsoft若要获取有关 Microsoft 组件的调试符号的符号服务器。 有关详细信息有关 Microsoft 符号服务器,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
311503 (http://support.microsoft.com/kb/311503/ ) 使用 Microsoft 符号服务器获取调试符号文件
UMDH 将尝试通过查找符号文件_NT_SYMBOL_PATH 环境变量。设置从路径命令命令提示符处可能类似于以下内容:
设置 _NT_SYMBOL_PATH = SRV * c:\LocalSymbolCache
有关如何设置符号调试的其他信息信息,请参阅本文后面的"调试符号"一节。

完成这些步骤后,您就可以使用 UMDH 实用程序。

与 UMDH 捕获堆转储

UMDH 是一个实用工具将转储有关堆的信息,分配的进程。此信息包括为每个的调用堆栈分配,通过该调用堆栈,所做的分配数和通过该调用堆栈占用的字节数。例如:
00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00053
           ntdll!RtlDebugAllocateHeap+0x000000FD
           ntdll!RtlAllocateHeapSlowly+0x0000005A
           ntdll!RtlAllocateHeap+0x00000808
           MyApp!_heap_alloc_base+0x00000069
           MyApp!_heap_alloc_dbg+0x000001A2
           MyApp!_nh_malloc_dbg+0x00000023
           MyApp!_nh_malloc+0x00000016
           MyApp!operator new+0x0000000E
           MyApp!LeakyFunc+0x0000001E
           MyApp!main+0x0000002C
           MyApp!mainCRTStartup+0x000000FC
           KERNEL32!BaseProcessStart+0x0000003D
				
此 UMDH 输出显示了 21280 (0x5320) 分配的字节数从调用堆栈的总和。21280 字节分配从 20 (0x14)分隔的 1064 字节 (0x428) 的分配。在给定调用堆栈BackTrace00053 的标识符。

生成堆转储文件分配,则必须使用 Gflags.exe 实用工具,也包括了与该工具Windows 的调试工具的产品,以便知道这些操作系统您想要跟踪分配的内核。

假定您需要若要为 Notepad.exe 转储 heap(s) 内容。您必须先启用堆栈跟踪要测试的应用程序的收购。默认情况下此功能未启用。要启用此功能的命令如下所示:
gflags-i notepad.exe + 必须
该命令不会启用的进程的堆栈跟踪已在运行,但它允许的所有将来执行的堆栈跟踪Notepad.exe。 或者,您可以设置 GFLAGS 用户通过标志(不带任何参数来获取在用户界面中运行 Gflags.exe) 的接口。使用" -必须 gflags 禁用堆栈跟踪所需的选项完成调试。

当您将设置 Gflags.exe,通过这些图像标志并设置调试符号,您就可以启动记事本 (应用程序正在使用 UMDH)。在程序启动后,您必须确定只需启动记事本进程的进程 ID (PID)。此命令如下所示:
tlist
您可以找到从 TLIST 应用程序的输出的 PID。PID 信息也可以获得在任务管理器中。假定为 PID您刚才启动记事本过程是 124。您可以使用 UMDH 来获取堆转储,使用以下命令:
umdh-p: 124-f:notepad124.log
结果: 必须在记事本进程的完整堆转储Notepad124.log 文件。此文件可用于显示所有已进行的分配和分配做修饰。

使用比较 UMDH 日志的 Umdh.exe

而 UMDH 日志文件有关包含有价值的信息对于进程而言,如果您不关心查找堆的当前状态内存泄漏漏洞,它可能会更有价值进行比较的两个日志输出和找出哪些调用堆栈过两个转储文件之间的最大增长。Umdh.exe 实用程序有助于比较两个 UMDH 日志,以提供的分析二者之间的差异。一旦有两种日志在不同捕获时间间隔,然后可以使用以下命令:
UMDH dh1.log dh2.log &gt; cmp12.txt
-或者-
UMDH-d dh1.log dh2.log &gt; cmp12.txt
" -d 命令行选项指示要显示而不是十进制的 UMDH十六进制。命令的输出进行比较的差异分配之间的两个记录,并提供类似的信息以下内容:
+ 5320 (f110-9df0) 3a allocs BackTrace00053总增加 = = 5320
对于 UMDH 日志文件中的每个反向跟踪,则比较两个日志文件之间进行。这种情况下显示的是最后一个日志文件在 UMDH 中指定命令行有 0xF110 个字节分配同时第一在 UMDH 命令行中的日志有 0x9DF0 个字节分配给同一个反向跟踪(调用堆栈)。"5320"是分配的字节数中的差异。在中此例中没有更多字节分配的时间之间的 0x5320,两个日志捕获。字节是来自于由标识的调用堆栈"BackTrace00053"。

下一步是找出中的反向跟踪。如果您打开的第二个日志文件和搜索 BackTrace00053您可能会发现某些东西,类似于以下形式:
00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00053
           ntdll!RtlDebugAllocateHeap+0x000000FD
           ntdll!RtlAllocateHeapSlowly+0x0000005A
           ntdll!RtlAllocateHeap+0x00000808
           MyApp!_heap_alloc_base+0x00000069
           MyApp!_heap_alloc_dbg+0x000001A2
           MyApp!_nh_malloc_dbg+0x00000023
           MyApp!_nh_malloc+0x00000016
           MyApp!operator new+0x0000000E
           MyApp!LeakyFunc+0x0000001E
           MyApp!main+0x0000002C
           MyApp!mainCRTStartup+0x000000FC
           KERNEL32!BaseProcessStart+0x0000003D
				
当您查看调用堆栈时,您可以看到, LeakyFunc 函数分配内存通过 Visual c + + 运行时库运算符新函数。如果您发现的分配数的增加以及您需要更多的转储文件,您可能会认为该内存不会被释放。

启用堆栈跟踪

UMDH 日志中的最重要信息是堆栈跟踪堆分配。您可以分析用于验证过程是否泄漏堆内存。默认情况下不能获得这些堆栈跟踪信息。您可以启用此功能每个进程或系统范围内的功能。使用以下命令启用堆栈跟踪系统范围内:
gflags-r + 必须
此命令后,重新启动计算机。为每个进程启用后,该命令如下所示:
gflags-i 应用程序名称 + 必须
位置 应用程序名称 包括的扩展名 (可执行文件的文件名例如,Services.exe,Lsass.exe)。该命令不会启用堆栈跟踪对于已在运行的进程。因此,对于您不能的进程重新启动 (例如,服务、 lsass,winlogon),您必须重新启动您的测试计算机。

使用以下命令验证设置的具有已设置系统范围或特定进程: 系统范围内:
gflags-r
特定进程:
gflags-i 应用程序名称
默认情况下的最大堆栈跟踪深度为 16。如果您希望请参阅更深层次的修饰,您可以通过运行 GFLAGS 增加这。单击以选中 系统注册表然后键入新深度 最大值。堆栈跟踪捕获深度 编辑控件。单击" 应用然后重新启动计算机。
重要: 如果您使用的 Windows NT 4.0 服务包 6,则必须使用必须使用 Umdh_nt4.exe,而不是 Umdh.exe,并且您的 gflags-r 若要设置系统范围堆栈跟踪的命令。请确保您重新启动计算机。Umdh_nt4 堆栈跟踪不适用于每个进程在 Windows NT 版本 4 的基础。必须将它设置为整个系统。

调试符号

若要使用 UMDH 最重要的步骤之一是确保您有良好的符号文件 (.dbg 或.pdb 文件) 以取得良好的堆栈跟踪。至少,您需要的 Kernel32.dbg 和 Ntdll.dbg 的符号文件。您可以获取您可能需要为您找出更多的附加调试符号有关哪些组件泄漏内存。 有关详细信息有关如何获取有关 Microsoft 的调试符号文件组件,单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
311503 (http://support.microsoft.com/kb/311503/ ) 使用 Microsoft 符号服务器获取调试符号文件
有关如何使用的其他信息Microsoft 符号服务器以及如何获取 Windows 符号文件包,请访问下面的 Microsoft Web 站点:
http://www.microsoft.com/whdc/devtools/ddk/default.mspx (http://www.microsoft.com/whdc/devtools/ddk/default.mspx)
在生成 Visual c + + 的组件时,很重要的您没有程序数据库以进行编辑并继续选择 c + +编译器选项。而应选择程序数据库。若要设置符号路径,初始化 _NT_SYMBOL_PATH 环境变量对要使用的路径。您可以使用 Microsoft 符号服务器来获取有关 Microsoft 的符号组件。
311503 (http://support.microsoft.com/kb/311503/ ) 使用 Microsoft 符号服务器获取调试符号文件
请按照下列步骤来设置 _NT_SYMBOL_PATH环境变量:
  1. 在控制面板中,双击 系统.
  2. 单击 高级 选项卡,然后单击 环境变量。
也可以设置 _NT_SYMBOL_PATH 环境变量命令窗口运行 UMDH 之前。

请注意: 还包含的路径中的组件的 Pdb 您应用程序。例如,将 _NT_SYMBOL_PATH 的路径设置为下列:
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols;c:\myapplicationssymbols
此路径的第一部分指向 Microsoft 符号服务器和正在使用的符号将被下载,在 c:\symbols 中的状态文件夹。跟分号的部分是 PDB 文件的路径(符号文件) 专为泄漏的应用程序。

调用 UMDH

是唯一必需的命令行参数 UMDH -p 选项,它指定从该进程的 PID 堆将获取转储。可以通过使用任务管理器中获得 PID 或Tlist.exe 程序。对于一个类似于下面的命令,将该日志转储到标准输出:
umdh-p: PID
UMDH 也将显示各种信息性消息标准错误,并因此如果不进行定向,它与混合的真实的日志。若要收集文件中的 UMDH 信息性消息,请使用以下命令:
umdh-p: PID 2>umdh.msg
如果您想要收集的日志的情况下在文件中,UMDH 将被转储使用下列命令之一:
umdh-p: PID &gt; umdh.log
-或者-
umdh-p: PID-f:umdh.log
这些命令是等效的。

默认的日志,通过获取 UMDH 包含按排序的堆消费者的枚举分配计数。如果出于调试目的,您还需要所有的转储文件分配的块和其相应的堆栈跟踪, -d 可以使用选项:
umdh-p: PID d
如果使用此命令时,您可能会看到 UMDH 中的以下日志文件:
分配跟踪 BackTrace00046: 005F69A0005F6150
这些都是要进行该操作的分配的内存地址调用堆栈。如果您的调试器附加到进程中,您可转储若要查看已分配什么这些地址的内存的内容。

如果日志中包含太多的信息,它可以是仅限于已分配的大用户计数某些阈值以上。使用下面的命令:
umdh-p: PID-t: 阈值
所有命令行选项 (例如, -p、-f-t,-d) 可以同时按任意顺序指定。下面是更难的命令行示例:
umdh-p: 123-t: 1000-f:umdh.log-d
此命令会为到 PID 为 123 的进程的堆转储Umdh.log 文件中。它转储只栈跟踪该帐户为超过 1000分配和它还将转储堆块的地址分配到每个堆栈跟踪。

另一个有用的 UMDH 选项" -l 选项。这将导致以打印的文件和行号只要可能,就调用堆栈。

UMDH 输出说明

如果将您重定向日志文件 ( umdh-p: PID-f:umdh.log),其内容是类似于以下内容,这获得从运行的记事本进程:
UMDH: Logtime 2000-06-28 10:54 - Machine=MYMachine - PID=704
   *********** Heap 00270000 Information ********************
       Flags: 58000062
       Number Of Entries: 87
       Number Of Tags: <unknown>
       Bytes Allocated: 00008DF0
       Bytes Committed: 0000A000
       Total FreeSpace: 00001210
       Number of Virtual Address chunks used: 1
       Address Space Used: <unknown>
       Entry Overhead: 8
       Creator:  (Backtrace00007)
           ntdll!RtlDebugCreateHeap+0x00000196
           ntdll!RtlCreateHeap+0x0000023F
           ntdll!LdrpInitializeProcess+0x00000369
           ntdll!LdrpInitialize+0x0000028D
           ntdll!KiUserApcDispatcher+0x00000007
   *********** Heap 00270000 Hogs ********************
   000001A0 bytes in 0x4 allocations (@ 0x00000068) by: BackTrace00031
           ntdll!RtlDebugAllocateHeap+0x000000FB
           ntdll!RtlAllocateHeapSlowly+0x0000005B
           ntdll!RtlAllocateHeap+0x00000D81
           ntdll!LdrpAllocateDataTableEntry+0x00000039
           ntdll!LdrpMapDll+0x000002A4
           ntdll!LdrpLoadImportModule+0x0000010D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpLoadImportModule+0x0000011D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpLoadImportModule+0x0000011D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpInitializeProcess+0x000009DC
           ntdll!LdrpInitialize+0x0000028D
           ntdll!KiUserApcDispatcher+0x00000007

   000001A0 bytes in 0x4 allocations (@ 0x00000068) by: BackTrace00034
           ntdll!RtlDebugAllocateHeap+0x000000FB
           ntdll!RtlAllocateHeapSlowly+0x0000005B
           ntdll!RtlAllocateHeap+0x00000D81
           ntdll!LdrpAllocateDataTableEntry+0x00000039
           ntdll!LdrpMapDll+0x000002A4
           ntdll!LdrpLoadImportModule+0x0000010D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpLoadImportModule+0x0000011D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpLoadImportModule+0x0000011D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpLoadImportModule+0x0000011D
           ntdll!LdrpWalkImportDescriptor+0x0000008B
           ntdll!LdrpInitializeProcess+0x000009DC
           ntdll!LdrpInitialize+0x0000028D
           ntdll!KiUserApcDispatcher+0x00000007
				
日志中包含过程中每个堆的转储。在此示例中,日志开始地址 270000 堆集。之后的几个全局计数器堆中,日志中包含的堆栈跟踪的不断降低按排序顺序转储大多数分配的负责。当您进行比较的动态在不同时间,使用的内存可以推断出中发生的问题进程,如果任何堆使用类似于泄漏。

您可以使用 UMDH 时遇到的问题

当您使用 UMDH 时最常见的错误原因是堆栈不启用跟踪。此外,不正确的符号 Ntdll.dll 防止从 UMDH在运行。其他符号文件 ; 对于 UMDH 运行,但日志文件包含堆栈跟踪的没有函数名称只是相对地址模块内。距离较远的第三个错误指定错误的 PID。以下当您试图为不具有的进程运行 UMDH 时的错误消息结果启用堆栈跟踪:
C:\>umdh-p: 1140 UMDH: Logtime2000-06-28 12: 43-计算机 = MyMachine-PID = 1140年连接...模块枚举已完成。SymGetSymFromName (过程、 ntdll!RtlpStackTraceDataBase,xxx) 失败,LastError = 126 UmdhGetAddrFromName 找不到堆栈跟踪数据库指针 (ntdll!RtlpStackTraceDataBase)。ntdll.dll 符号不正确。我们必须能够看到非导入元件。
使用以下命令请仔细检查您调查进程的设置:
gflags-i 的应用程序名称
您依赖于整个系统堆栈时,请使用下面的命令跟踪:
gflags-r
这些命令显示设置,应用程序的标记列表。请注意,在系统范围内堆栈跟踪的情况下,该功能可能显示为但如果您未重新启动计算机后运行活动 gflags-r + 必须 此命令,它实际上未被激活。如果您想要知道每个已启用的堆栈跟踪的应用程序,您可以查看的 USTEnabled 键在以下注册表项中:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image 文件执行选项
如果已启用,堆栈跟踪的进程上运行 UMDH,但您没有重新启动该应用程序由于设置标志,您可能会收到您的日志中的下列消息:
堆栈跟踪程序不保存此分配 (索引 = = 0)
如果您运行未设置您可能正确的符号路径或符号不正确,并且您运行 UMDH,在日志中收到一条错误消息。但是,您可能只能收到不正确或令人误解的修饰。若要验证您具有正确的符号,请启动NTSD 系统调试进程,例如:
ntsd 记事本
然后,从调试器控制台,运行 LD 若要加载的模块的符号信息的命令和 LM 若要列出哪些模块有加载其元件的命令。如果输出 LM 命令显示加载的导出符号,这些符号不是很好。如果已加载的 PDB 符号,这些符号正常工作。您可能会收到下面的错误消息如果指定了错误的 PID:
C:\>umdh-p: 1000 UMDH: Logtime 2000-06-28 09: 45-计算机 = MyMachine-PID = 1000年连接...失败的 OpenProcess,LastError = 0x57

从 Visual Basic 中调用 UMDH

它可能很有用,有时会随着时间的推移转储的日志数目由于泄漏可能不是很明显,因此在第一次。例如,如果您怀疑活动服务器页面 (ASP) Web 应用程序正在泄漏内存,它可能有助于写出到 shells 的 Visual Basic 中的 COM 组件UMDH。然后可以从 ASP 页中调用该组件。

"下面是一些 Visual Basic 代码的调用 UMDH,并创建日志文件基于当前时间:
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
      Public Function GetProcessID()
      GetProcessID = GetCurrentProcessId()
      End Function  
   .
   .
   .
      Dim strTime As String

      Dim sProcID As String
      sProcID = GetProcessID()
      strTime = "MYLOG_" & Format(Now(), "hhmm")
     
      Shell ("C:\UMDH\umdh -p:" & sProcID & " -f:d:\logs\" & strTime & ".txt")
				

使用 Windows NT 4.0 Service Pack 6a UMDH (SP6a)

UMDH 实用程序附带的调试工具在 Windows NT 4.0 Windows 产品无法正常工作。自解压可执行文件(Umdhnt4tools.exe) 是附带这篇文章,其中包含以下在 NT 4.0 上使用的工具:
  • Umdh_nt4.exe 和 Dbghelp.dll
    这是 Windows NT4.0 SP6 版本的 UMDH 实用程序。
  • Dhcmp.exe
    此实用程序用于比较两个 UMDH转储以确定其中可能的内存泄漏会发生。
"下面的文件是可从 Microsoft 下载下载中心:
收起这个图片 展开这个图片
下载
立即下载 Umdhnt4tools.exe (http://download.microsoft.com/download/win2000srv/Utility/1.0/NT45/EN-US/umdhnt4tools.exe)
发布日期: 2002 2002年 8 月 28日日

有关如何下载 Microsoft 支持文件的详细信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
119591 (http://support.microsoft.com/kb/119591/ ) 如何从在线服务获得 Microsoft 支持文件
Microsoft 扫描此文件中的病毒。Microsoft 使用该文件被发送的日期上可用的最新病毒检测软件。该文件存储在安全性得到增强的服务器,以帮助防止对文件进行任何未经授权的更改。 将 Umdh_nt4.exe 和 Dbghelp.dll 放在一个文件夹,然后在将其第一次在 PATH 环境变量。而不是使用 Umdh_nt4.exeUMDH。

在计算机上运行的 Windows NT 4.0,您必须使用若要设置系统范围堆栈跟踪的 Gflags.exe。例如:
gflags-r
请确保您重新启动计算机。Umdh_nt4 堆栈跟踪每个进程的基于 Windows NT 4.0 版上无法正常工作。它是为设置整个系统。

UMDH_NT4 是与 UMDH 不同之处在于它不将日志文件进行比较。例如,您不能执行以下操作:
UMDH_NT4 dh1.log dh2.log &gt; cmp12.txt
您必须使用 Dhcmp.exe 实用程序包含与这篇文章。该命令与以下类似:
DHCMP dh1.log dh2.log &gt; cmp12.txt

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值