小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

實(shí)戰(zhàn):結(jié)合Dr.Watson系統(tǒng)日志和Vc6來定位多線程環(huán)境下程序異常退出的錯(cuò)誤...

 ShaneWu 2008-12-10

實(shí)戰(zhàn):結(jié)合Dr.Watson系統(tǒng)日志和Vc6來定位多線程環(huán)境下程序異常退出的錯(cuò)誤

    當(dāng)開發(fā)的軟件發(fā)布以后,在客戶那運(yùn)行時(shí)可能會(huì)因?yàn)楦鞣N原因?qū)е鲁绦蛲顺?。這種情況很尷尬,很明顯我們無法在客戶機(jī)器上裝個(gè)Visual Studio調(diào)試,所以必須有機(jī)制來收集出錯(cuò)的信息。軟件本身的運(yùn)行日志能提供部分信息,但是可能還不夠。Windows系統(tǒng)為此提供了解決方 案:Dr.Watson工具。Dr.Watson也算是一個(gè)小巧的調(diào)試器,32位的版本名字是drwtsn32.exe??捎糜诋?dāng)系統(tǒng)中有進(jìn)程發(fā)生異常崩 潰時(shí)采集信息。下面結(jié)合一個(gè)例子看一下其用法。

 

先把測(cè)試代碼貼一下:

  1. /********************************************************************/
  2. /* 程序:lesson_2, 結(jié)合Dr.Watson與工程map文件定位錯(cuò)誤                                  */
  3. /* 功能:多線程環(huán)境中利用除0錯(cuò)誤使程序產(chǎn)生異常,被Dr.Watson捕獲之       */
  4. /* 作者:coding (http://blog.csdn.net/coding_hello)                                                     */
  5. /* 日期:2008-09-29                                                                                                    */
  6. /********************************************************************/
  7. #include <stdio.h>
  8. #include <process.h>
  9. #include <windows.h>
  10. const int cnThreadnum = 4;
  11. UINT WINAPI Worker(LPVOID lpParam)
  12. {
  13.     srand((DWORD)lpParam);
  14.     DWORD dwTid = GetCurrentThreadId();
  15.     int k=100;
  16.     while(k--)
  17.     {
  18.         printf("tid[%u] tmp = %d\n", dwTid, RAND_MAX/(rand()%cnThreadnum));
  19.         Sleep(10);
  20.     }
  21.     return 0;
  22. }
  23. int main(int argc, char* argv[])
  24. {
  25.     HANDLE hThd[cnThreadnum] = {0};
  26.     for(DWORD i=0; i<cnThreadnum; i++)
  27.     {
  28.         hThd[i] = (HANDLE)_beginthreadex(NULL, 0, Worker, (LPVOID)i, 0, NULL);
  29.     }
  30.     printf("Wait...\n");
  31.     WaitForMultipleObjects(cnThreadnum, hThd, TRUE, INFINITE);
  32.     for(int k=0; k<cnThreadnum; k++)
  33.     {
  34.         CloseHandle(hThd[k]);
  35.     }
  36.     printf("Finish!\n");
  37.     system("pause");
  38.     return 0;
  39. }

程序已開始就啟動(dòng)了4個(gè)線程,然后 主線程等待所有的線程結(jié)束。線程函數(shù)中可能會(huì)因?yàn)镽AND_MAX/(rand()%10)導(dǎo)致出現(xiàn)除0的錯(cuò)誤。這里注意,編譯的時(shí)候選擇Link頁, 把"Generate mapfile"前面勾上。一般來說我就這樣用了。但是還可以讓map信息更詳細(xì)一些,在最下面的"Project Options"的最后面手工敲入:"/mapinfo:lines",注意,跟前面內(nèi)容要用空格隔開。然后再編譯。

 

因?yàn)槭且菔綝r.Waston,所以我們?cè)诿钚邢扔?strong>drwtsn32 -i的命令注冊(cè)Dr.Watson為默認(rèn)調(diào)試器(下次啟動(dòng)VC6的時(shí)候,在菜單option-->debug里面確認(rèn)just-in-time debugging選中,就會(huì)把VC6恢復(fù)為默認(rèn)調(diào)試器的)。注冊(cè)完以后,我們看看注冊(cè)表是否滿足需要了。

 

注冊(cè)表信息

 

看看注冊(cè)表中 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug,其中的Auto鍵的值如果是0的話,程序出錯(cuò)后還會(huì)彈出錯(cuò)誤提示。我們需要的是出錯(cuò)后安靜的處理 掉,客戶知道了多不好~所以,改成1。下面的Debugger已經(jīng)是drwtsn32了,很好。最后的UserDebuggerHotKey是調(diào)試器的熱 鍵,我們不需要。接下來,還是在命令行敲Drwtsn32,回車,終于看到Drwtsn32的廬山真面目了:

 

Dr.Watson

 

上面是日志文件和dump文件的保存路徑。這次我們要看的是日志,dump 文件下次再說。符號(hào)表我一般都勾上了,有的話就更好不是~ 重點(diǎn)是下面的應(yīng)用程序錯(cuò)誤(&R)這里,如果日志中有信息,就會(huì)在下面一條一條以紀(jì)錄的形式顯示出來。如果你的Drwatson中確實(shí)有日志的 話,可以點(diǎn)清除把以前的都刪掉。既然已經(jīng)見過面了,那就把它關(guān)掉吧,需要時(shí)再打開,反正它自己也不會(huì)實(shí)施刷新。

 

好,現(xiàn)在一切就緒了!運(yùn)行一下程序~ 只見嗖的一下,程序就停了。趕緊再把Dr.Watson請(qǐng)出來看看~

Error info

 

這次我們看到應(yīng)用程序錯(cuò)誤那里有了一條記錄,把它選中變藍(lán)后點(diǎn)上面的查看按 鈕。于是又出來一個(gè)對(duì)話框,顯示“發(fā)生應(yīng)用程序意外錯(cuò)誤:”云云,內(nèi)容很長,信息相當(dāng)多。嗯,很好,很強(qiáng)大,這就是我們要的。考慮到這個(gè)框小了點(diǎn),可以 Ctrl+Shift+END全選后copy出來,用記事本看哈。在記事本中查找"錯(cuò)誤 ->",然后就會(huì)看到個(gè)這:

 

錯(cuò)誤 ->00401087 f7f9            idiv    eax,ecx

 

沒錯(cuò),這就是錯(cuò)誤的位置。仔細(xì)看看上下文,分析分析。由于是一個(gè)多線程的程 序,所以這里把出錯(cuò)的線程單獨(dú)剝離出來。如下所示,每個(gè)線程的信息分為幾個(gè)部分:一開始是錯(cuò)誤發(fā)生時(shí)寄存器的信息;然后是當(dāng)前發(fā)生錯(cuò)誤的指令的前后各10 條指令(什么是10條,不是20條或者2條?因?yàn)镈r.Watson里面默認(rèn)設(shè)置的就是10條呀~,你剛才又沒改);接下來是堆棧反向跟蹤信息,也就是函數(shù)的逆向調(diào)用序列;最后是原始堆棧信息,可以獲得參數(shù),返回地址,局部變量之類的信息。

 

 

  1. *----> 線程 ID 0x2714 的狀態(tài)轉(zhuǎn)儲(chǔ) <----*
  2. eax=00007fff ebx=003724b8 ecx=00000000 edx=00000000 esi=0063ff2c edi=0063ff80
  3. eip=00401087 esp=0063ff2c ebp=0063ff80 iopl=0         nv up ei pl zr na pe nc
  4. cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
  5. 函數(shù): lesson_2!Worker
  6.         0040106b 7441                   je      lesson_2!Worker+0x8e (004010ae)
  7.         0040106d e86e020000       call    lesson_2!rand (004012e0)
  8.         00401072 8bc8                   mov     ecx,eax
  9.         00401074 81e103000080   and     ecx,80000003h
  10.         0040107a 7905                   jns     lesson_2!Worker+0x61 (00401081)
  11.         0040107c 49                       dec     ecx
  12.         0040107d 83c9fc                or      ecx,0FFFFFFFCh
  13.         00401080 41                      inc     ecx
  14.         00401081 b8ff7f0000        mov     eax,7FFFh
  15.         00401086 99                      cdq
  16. 錯(cuò)誤 ->00401087 f7f9               idiv    eax,ecx
  17.         00401089 50                      push    eax
  18.         0040108a 8b55fc               mov     edx,dword ptr [ebp-4]
  19.         0040108d 52                      push    edx
  20.         0040108e 681cd04200       push    offset lesson_2!`string' (0042d01c)
  21.         00401093 e898010000       call    lesson_2!printf (00401230)
  22.         00401098 83c40c               add     esp,0Ch
  23.         0040109b 8bf4                   mov     esi,esp
  24.         0040109d 6a0a                   push    0Ah
  25.         0040109f ff15d8714300    call    dword ptr [lesson_2!_imp__Sleep (004371d8)]
  26.         004010a5 3bf4                   cmp     esi,esp
  27. *----> 堆棧反向跟蹤 <---*
  28. ChildEBP   RetAddr   Args to Child              
  29. 0063ff80   004015e2   00000001  00000000  00000000  lesson_2!Worker+0x67
  30. 0063ffb8   7c824829   003724b8  00000000  00000000  lesson_2!_threadstartex+0xb2
  31. WARNING: Stack unwind information not available. Following frames may be wrong.
  32. 0063ffec    00000000  00401530  003724b8  00000000  kernel32!GetModuleHandleA+0xdf
  33. *----> 原始堆棧轉(zhuǎn)儲(chǔ) <----*
  34. 000000000063ff2c   00 00 00 00 00 00 00 00 - b8 24 37 00  cc  cc  cc  cc  .........$7.....
  35. 000000000063ff3c   cc  cc cc  cc  cc  cc cc  cc - cc  cc  cc  cc  cc  cc  cc  cc  ................
  36. 000000000063ff4c   cc  cc cc  cc  cc  cc cc  cc - cc  cc  cc  cc  cc  cc  cc  cc  ................
  37. 000000000063ff5c   cc  cc cc  cc  cc  cc  cc cc - cc  cc  cc  cc  cc  cc  cc  cc  ................
  38. 000000000063ff6c   cc  cc cc  cc  cc  cc  cc cc - cc  cc  cc  cc  06 00 00  00  ................
  39. 000000000063ff7c   14 27 00 00 b8 ff  63 00 - e2 15 40  00  01 00 00  00  .'....c...@.....
  40. 000000000063ff8c   00 00 00 00 00 00 00 00 - b8 24 37 00  94 00  00 c0  .........$7.....
  41. 000000000063ff9c   00 00 00 00 8c ff   63 00 - 60 fb 63 00  dc  ff   63 00  ......c.`.c...c.
  42. 000000000063ffac    b4 65 40 00 b0 d1 42 00 - 00 00 00 00 ec  ff   63 00  .e@...B.......c.
  43. 000000000063ffbc   29 48  82 7c b8 24 37 00 - 00 00 00 00 00 00  00 00  )H.|.$7.........
  44. 000000000063ffcc    b8 24 37 00 94 00 00 c0 - c4  ff  63 00 60 fb  63  00  .$7.......c.`.c.
  45. 000000000063ffdc    ff   ff  ff  ff  60 1a  82 7c - 30 48 82 7c 00 00 00  00  ....`..|0H.|....
  46. 000000000063ffec    00 00 00 00 00 00 00 00 - 30 15 40 00 b8 24 37  00  ........0.@..$7.
  47. 000000000063fffc    00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................
  48. 000000000064000c  00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................
  49. 000000000064001c  00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................
  50. 000000000064002c  00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................
  51. 000000000064003c  00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................
  52. 000000000064004c  00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................
  53. 000000000064005c  00 00 00 00 00 00 00 00 - 00 00 00 00 00  00 00 00  ................

盡管這里可以簡單的利用錯(cuò)誤處指出的地址0x401087直接定位,那是因?yàn)檫@是很簡單的情況。所以我決定還是簡單講一下在實(shí)際的復(fù)雜得多的環(huán)境中如何分析這些數(shù)據(jù)。

 

1.定位出錯(cuò)的模塊。

我們看到錯(cuò)誤的地址是0x401087,應(yīng)該先確認(rèn)這個(gè)地址是在哪個(gè)模塊中。在錯(cuò)誤日志中查找“模塊清單”,能找到以下內(nèi)容:

  1. *----> 模塊清單 <----*
  2. 0000000000400000 - 000000000043a000: D:\DebugEasy\lesson_2\Debug\lesson_2.exe
  3. 0000000074ae0000 - 0000000074b45000: C:\windows\system32\USP10.dll
  4. 0000000076180000 - 000000007619d000: C:\windows\system32\IMM32.DLL
  5. 0000000076eb0000 - 0000000076ec3000: C:\windows\system32\Secur32.dll
  6. 0000000077bd0000 - 0000000077c18000: C:\windows\system32\GDI32.dll
  7. 0000000077c20000 - 0000000077cbf000: C:\windows\system32\RPCRT4.dll
  8. 0000000077e10000 - 0000000077ea0000: C:\windows\system32\USER32.dll
  9. 0000000077f30000 - 0000000077fdb000: C:\windows\system32\ADVAPI32.dll
  10. 000000007c800000 - 000000007c92b000: C:\windows\system32\kernel32.dll
  11. 000000007c930000 - 000000007ca00000: C:\windows\system32\ntdll.dll
  12. 000000007f000000 - 000000007f009000: C:\windows\system32\LPK.DLL

這里清楚的指出0000000000400000 - 0000000000439000這個(gè)范圍的地址是系統(tǒng)分配給lesson_2.exe的。我們得到的錯(cuò)誤地址是0x401087,所以可以確定錯(cuò)誤就是 發(fā)生的lesson_2.exe模塊。實(shí)際上很多應(yīng)用都還有些自己的動(dòng)態(tài)庫之類的,定位到具體的模塊后才能更具體的結(jié)合代碼分析。有時(shí)候出錯(cuò)的地址是屬于 kernel32,ntdll.dll之類的系統(tǒng)函數(shù),這種情況下需要分析堆棧信息來確定錯(cuò)誤模塊。

 

2.分析當(dāng)前發(fā)生錯(cuò)誤的直接原因

我們看到錯(cuò)誤的指令是:idiv eax,ecx。基本上訪問eax和ecx都不會(huì)有問題,不然就是cpu有問題了。所以應(yīng)該是除法指令出錯(cuò)??纯辞懊娴募拇嫫鞯男? 息,eax=00007fff,也就是RAND_MAX,ecx=00000000,除0錯(cuò)誤。對(duì)于我們這個(gè)例子,有了這個(gè)信息就足夠定位到問題了。不過 還是看看我們還能收集到些什么信息,畢竟實(shí)際環(huán)境可不會(huì)這么簡單。

 

3.分析當(dāng)前線程的調(diào)用堆棧。

ChildEBP   RetAddr    Args to Child             
0063ff80    004015e2    00000001  00000000 00000000 lesson_2!Worker+0x67
0063ffb8    7c824829    003724b8  00000000 00000000 lesson_2!_threadstartex+0xb2

 

在堆棧反向跟蹤部分,這個(gè)信息很清晰。 _threadstartex系統(tǒng)函數(shù)調(diào)用了我們的線程函數(shù)Worker。當(dāng)前函數(shù)的返回地址是0x4015e2,接著是3個(gè)參數(shù)(注意:不一定都有效, 顯然不是所有的函數(shù)都有3個(gè)參數(shù)。實(shí)際上通過分析其dump文件能看到我們的例子中只有第一個(gè)參數(shù)有效,即1,是作為線程參數(shù)傳入的lpParam)。這 里我們結(jié)合map文件看看是不是跟這里記錄的一樣。在工程的debug目錄里,有個(gè)擴(kuò)展名為map的文件,用一般的文本編輯器就能打開。這文件太長了,節(jié) 選一部分看看:

  1.  lesson_2
  2.  Timestamp is 48e0197a (Mon Sep 29 06:50:11 2008)
  3.  Preferred load address is 00400000
  4.  Start                      Length     Name                   Class
  5.  0001:00000000 0001bae7H .text                    CODE
  6.  0001:0001bae7 00010009H .textbss               CODE
  7.  0002:00000000 00002207H .rdata                  DATA
  8.  0002:00002207 00000000H .edata                  DATA
  9.  0003:00000000 00000104H .CRT$XCA        DATA
  10.  0003:00000104 00000104H .CRT$XCZ        DATA
  11.  0003:00000208 00000104H .CRT$XIA         DATA
  12.  0003:0000030c 00000109H .CRT$XIC          DATA
  13.  0003:00000418 00000104H .CRT$XIZ          DATA
  14.  0003:0000051c 00000104H .CRT$XPA         DATA
  15.  0003:00000620 00000104H .CRT$XPX         DATA
  16.  0003:00000724 00000104H .CRT$XPZ         DATA
  17.  0003:00000828 00000104H .CRT$XTA        DATA
  18.  0003:0000092c 00000104H .CRT$XTZ         DATA
  19.  0003:00000a30 0000407cH .data                     DATA
  20.  0003:00004ab0 00001b94H .bss                      DATA
  21.  0004:00000000 00000014H .idata$2                DATA
  22.  0004:00000014 00000014H .idata$3                DATA
  23.  0004:00000028 000001b0H .idata$4                DATA
  24.  0004:000001d8 000001b0H .idata$5                DATA
  25.  0004:00000388 0000076bH .idata$6                DATA
  26.   Address         Publics by Value              Rva+Base     Lib:Object
  27.  0001:00000020       ?Worker@@YGIPAX@Z          00401020 f   lesson_2.obj
  28.  0001:000000f0       _main                                            004010f0 f   lesson_2.obj
  29.  0001:00000212       _Sleep@4                                     00401212 f   kernel32:KERNEL32.dll
  30.  0001:00000218       _GetCurrentThreadId@0             00401218 f   kernel32:KERNEL32.dll
  31.  0001:0000021e       _CloseHandle@4                          0040121e f   kernel32:KERNEL32.dll
  32.  0001:00000224       _WaitForMultipleObjects@16    00401224 f   kernel32:KERNEL32.dll
  33.  0001:00000230       _printf                                          00401230 f   LIBCMTD:printf.obj
  34.  0001:000002d0       _srand                                           004012d0 f   LIBCMTD:rand.obj
  35.  0001:000002e0       _rand                                             004012e0 f   LIBCMTD:rand.obj
  36.  0001:00000320       __chkesp                                      00401320 f   LIBCMTD:chkesp.obj
  37.  0001:00000360       _system                                        00401360 f   LIBCMTD:system.obj
  38.  0001:00000470       __beginthreadex                            00401470 f   LIBCMTD:threadex.obj
  39.  0001:00000630       __endthreadex                               00401630 f   LIBCMTD:threadex.obj
  40.  0001:00000680       _mainCRTStartup                        00401680 f   LIBCMTD:crt0.obj
  41.  0001:000007d0       __amsg_exit                                  004017d0 f   LIBCMTD:crt0.obj
  42. 。。。。。。省略若干。。。。。
  43. Line numbers for .\Debug\lesson_2.obj(d:\debugeasy\lesson_2\lesson_2.cpp) segment .text
  44.     18 0001:00000020    19 0001:00000038    21 0001:00000044    22 0001:00000056
  45.     23 0001:0000005d    25 0001:0000006d    26 0001:0000009b    27 0001:000000ac
  46.     28 0001:000000ae    29 0001:000000b0    32 0001:000000f0    33 0001:00000108
  47.     34 0001:0000011a    36 0001:00000132    37 0001:00000152    39 0001:00000154
  48.     40 0001:00000161    42 0001:0000017a    44 0001:00000192    45 0001:000001a9
  49.     47 0001:000001ab    48 0001:000001b8    49 0001:000001c5    50 0001:000001c7

其中顯示了程序名,程序的時(shí)間戳,程序中的代碼分布,預(yù)定的加載地址,各個(gè)函數(shù)的起始地址,包括相對(duì)虛擬地址 (RVA)以及文件行與RVA的對(duì)應(yīng)關(guān)系等信息。我們看到預(yù)定的加載地址和我們?cè)谀K清單中看到的加載地址相同。很好,省得計(jì)算相對(duì)位置。一般來說Exe 總是加載到0x400000,并且總是能得到這個(gè)位置的。而動(dòng)態(tài)庫的話,墨認(rèn)是0x10000000,顯然如果有2個(gè)動(dòng)態(tài)庫就沒法都加載到同一個(gè)地址,需 要計(jì)算RVA。

 

剛才從堆棧反向跟蹤信息中我們看到當(dāng)前Worker函數(shù)的返回地址為0x401e52,在map文件中找找。很快 就能看到__beginthreadex函數(shù)是從0x401470開始,到0x401630結(jié)束。那就說明地址0x401e52就在 __beginthreadex函數(shù)中。這就對(duì)了,因?yàn)槲覀兙褪怯胈_beginthreadex函數(shù)啟動(dòng)的線程函數(shù)Worker,是吧~。順手看一下剛 才出錯(cuò)的地址0x401087,看看是在哪。再看看map文件,第一個(gè)函數(shù)就是?Worker@@YGIPAX@Z, 地址是0x00401020至0x4010f0(main函數(shù)),所以0x401087就是在執(zhí)行Worker函數(shù)中的指令。那么具體在哪一行呢?因?yàn)槌? 錯(cuò)的函數(shù)Worker在文件lesson_2.cpp中,所以我們查找lesson_2.cpp,就找到了下面的信息:

  1. Line numbers for .\Debug\lesson_2.obj(d:\debugeasy\lesson_2\lesson_2.cpp) segment .text
  2.     15 0001:00000020    16 0001:00000038    18 0001:00000044    19 0001:00000056
  3.     20 0001:0000005d    22 0001:0000006d    23 0001:0000009b    24 0001:000000ac
  4.     25 0001:000000ae    26 0001:000000b0    29 0001:000000f0    30 0001:00000108
  5.     31 0001:0000011a    33 0001:00000132    34 0001:00000152    46 0001:00000154
  6.     37 0001:00000161    39 0001:0000017a    41 0001:00000192    42 0001:000001a9
  7.     44 0001:000001ab    45 0001:000001b8    46 0001:000001c5    47 0001:000001c7

    我們看到前面是個(gè)數(shù)字,18、19、21啥的,后面是0001:00000020之類。前面的就是cpp文件中的行號(hào),后面是相對(duì)虛擬地址,我們的 0x401087在哪呢?又回到剛才說的默認(rèn)加載地址了。map中看到默認(rèn)加載地址是0x400000,而我們的exe在內(nèi)存中也是加載到 0x400000,所以相對(duì)位置就是RVA = 0x401087(錯(cuò)誤地址) - 0x400000(模塊在內(nèi)存中實(shí)際加載的地址) = 0x1067。不對(duì)啊,這里最大才到0x1c7,這是怎~么個(gè)情況?因?yàn)槊總€(gè)PE模塊之前都有0x1000字節(jié)的dos stub和PE格式信息。所以0x1087還要減掉0x1000,就剩下0x87了。再看看,大于0x5d,小于0x6d,所以就是第22行??纯创a中 的22行,printf("tid[%u] tmp = %d\n", dwTid, RAND_MAX/(rand()%cnThreadnum));沒錯(cuò),就是在這里RAND_MAX/0了~。說明前面根據(jù)Dr.Watson的日志分析的結(jié)果都是正確的,沒騙你噢~

 

       有時(shí)候堆棧反向跟蹤的信息并不準(zhǔn)確,多半是因?yàn)楹瘮?shù)中的局部變量在memcpy,strcpy之類的函數(shù)復(fù)制的數(shù)據(jù)過長,導(dǎo)致堆棧訪問越界。這種情況下,要仔細(xì)分析原始堆棧轉(zhuǎn)儲(chǔ),以后再說。

 

       在實(shí)際工作中,利用Dr.Watson輔助生成錯(cuò)誤日志,對(duì)于開發(fā)人員確實(shí)是很有幫助的。有需要的朋友,可以考慮這么試試。

 

       那今天就寫到這吧~ 天亮啦,飯去~

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多