• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            酸菜豬蹄的程序人生
            木下編程屯屯燙燙

            2010年11月16日

            MiniDumpWriteDump是MS DbgHelp.dll 中一個API, 用于導(dǎo)出當(dāng)前運行的程序的Dump. 這個dll程序系統(tǒng)中就有, 但是很多軟件, 都在自己的安裝目錄下保存了這個.dll的最新的版本.

            為了測試這個API, 參考網(wǎng)上一些資料, 寫了一個簡單的C++ 程序. 目的是當(dāng)有異常發(fā)生的時候, 自動生成Dump文件供之后的分析. 有了Dump文件, 我們就可以使用WinDBG等調(diào)試器來分析異常發(fā)生時的情況. 其實這個功能很多軟件都有, 比如QQ, 魔獸世界, 等等. 它們在出現(xiàn)了異常的時候會彈出一個對話框, 讓用戶輸入異常發(fā)生時的情況, 然后把異常的dump文件用email發(fā)回, 供開發(fā)者們分析修改bug.

            不過有一點, 這里需要程序的調(diào)試符號文件(pdb文件). 對于Debug版來說, 是生成的, 但是Release版來說默認(rèn)是不生成的. 可以設(shè)置VC的編譯器, 讓它在Release版的時候也生成調(diào)試信息. 這帶來一個新的問題, 因為.pdb里面是保存了源文件的信息的, 為了避免泄密, 可以采用VS中的CVPack工具, 從中去除敏感的信息.

            程序需要使用Dbghelp.hDbghelp.lib . 它們可以從MSDN找到.

            //最主要的函數(shù), 生成Dump
            static void DumpMiniDump(HANDLE hFile, PEXCEPTION_POINTERS excpInfo)
            {
            if (excpInfo == NULL) //如果沒有傳入異常, 比如是在程序里面調(diào)用的, 生成一個異常
            {
            // Generate exception to get proper context in dump
            __try
            {
            OutputDebugString(_T("raising exception\r\n"));
            RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
            }
            __except(DumpMiniDump(hFile, GetExceptionInformation()),
            EXCEPTION_CONTINUE_EXECUTION)
            {
            }
            }
            else
            {
            OutputDebugString(_T("writing minidump\r\n"));
            MINIDUMP_EXCEPTION_INFORMATION eInfo;
            eInfo.ThreadId = GetCurrentThreadId(); //把需要的信息添進(jìn)去
            eInfo.ExceptionPointers = excpInfo;
            eInfo.ClientPointers = FALSE;

                // 調(diào)用, 生成Dump. 98不支持
            // Dump的類型是小型的, 節(jié)省空間. 可以參考MSDN生成更詳細(xì)的Dump
            .
            MiniDumpWriteDump(
            GetCurrentProcess(),
            GetCurrentProcessId(),
            hFile,
            MiniDumpNormal,
            excpInfo ? &eInfo : NULL,
            NULL,
            NULL);
            }
            }

            下面的是程序部分:

            int _tmain(int argc, _TCHAR* argv[])
            {
            // 創(chuàng)建一個Dump文件
            HANDLE hFile = CreateFile( _T("MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE,
            0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
            int code;
            __try
            {   
            // 把自己實現(xiàn)的main函數(shù)包裝一下, 放在try .. except 塊中. 這樣出現(xiàn)了異常可以自動生成dump
            main_wrapper(argc, argv);
            }
            __except( code=GetExceptionCode(), DumpMiniDump(hFile, GetExceptionInformation() ),       EXCEPTION_EXECUTE_HANDLER ) //出現(xiàn)了異常, 記錄異常的code, 生成dump!!
            {
            printf("%x\n", code);
            wchar_t msg[512];
            wsprintf(msg, L"Exception happened. Exception code is %x", code);
            MessageBox(NULL, msg, L"Exception", MB_OK); //顯示消息給用戶
            }
            CloseHandle( hFile ); //關(guān)閉Dump文件
            getchar();
            return 0;
            }

            最下面是兩個測試的函數(shù), main_wrapper函數(shù)將調(diào)用test1, test1將會生成一個異常(非法內(nèi)存寫)

            void test1() {
            int *p;
            p = (int*)0x100;
            *p = 0; //寫0x100地址, 這個是非法的
            }

            void main_wrapper(int argc, _TCHAR* argv[]) {
            test1();
            }

            運行, 異常被捕獲了:

            同時, dump文件也生成了:


            用WinDBG打開Dump文件, 可以清楚的看出異常出現(xiàn)的情況:




            從中可以比較清楚的看到異常發(fā)生的情況(Exception code), 異常出現(xiàn)的地址(test1函數(shù), 偏移0x28). 因為這次測試的是Debug版, 有保存了源代碼的.pdb文件, 所以WinDbg把源代碼也列出來了. 這樣可以非常容易的發(fā)現(xiàn)問題.

            ============================================

            參考:
            DbgHelp中的DumpAPI例子: http://www.debuginfo.com/examples/src/effminidumps/MiniDump.cpp
            CrashReport: 程序出現(xiàn)異常的時候顯示發(fā)送錯誤的對話框, 并把Dump文件發(fā)送到指定的地址. http://code.google.com/p/crashrpt/
            XCrashReport: 與上面的類似的一個開源項目. http://www.codeproject.com/KB/debug/XCrashReportPt1.aspx
            posted @ 2010-11-16 10:41 cooelaf 閱讀(2740) | 評論 (1)編輯 收藏
             


            作者:<leohe.leohe@gmail.com>

                Linux系統(tǒng)中在應(yīng)用程序運行過程中經(jīng)常會遇到程序突然崩潰,提示:Segmentation fault,這是因為應(yīng)用程序收到了SIGSEGV信號。這個信號提示當(dāng)進(jìn)程發(fā)生了無效的存儲訪問,當(dāng)接收到這個信號時,缺省動作是:終止w/core。 終止w/core的含義是:在進(jìn)程當(dāng)前目錄生成core文件,并將進(jìn)程的內(nèi)存映象復(fù)制到core文件中,core文件的默認(rèn)名稱就是“core”(這是 Unix類系統(tǒng)的一個由來已久的功能)。
                事實上,并不是只有SIGSEGV信號產(chǎn)生coredump,還有下面一些信號也產(chǎn)生coredump:SIGABRT(異常終止)、SIGBUS(硬件 故障)、SIGEMT(硬件故障)、SIGFPE(算術(shù)異常)、SIGILL(非法硬件指令)、SIGIOT(硬件故 障),SIGQUIT,SIGSYS(無效系統(tǒng)調(diào)用),SIGTRAP(硬件故障)等。
                在程序的開發(fā)調(diào)試階段(尤其是大型軟件開發(fā)),發(fā)生程序異常崩潰時常規(guī)的調(diào)試方法常常是無比的痛苦:無窮的log中也不見得有什么有意義的信息。好在GDB提供和利用core文件進(jìn)行調(diào)試的途徑,大大方便了這類問題的調(diào)試。

                下面我們通過一個簡單的例子來看看怎么通過GDB來調(diào)試一個違規(guī)訪問內(nèi)存導(dǎo)致的程序崩潰。這里我們順便講講動態(tài)庫的調(diào)試。

            /******** mylib.h **********/
            #ifndef __MY_LIB_H__
            #define __MY_LIB_H__

            int add(int x, int y);

            #endif // __MY_LIB_H__
            /******** end **********/



            /******** mylib.c **********/
            #include <stdlib.h>
            #include "mylib.h"

            int add(int x, int y)
            {
                char* pc = NULL;
                *pc = 10;

                return x + y;
            }
            /******** end **********/

            /******** main.c **********/

            #include <stdio.h>
            #include <stdlib.h>

            #include "mylib.h"

            int main (void)
            {
                int ret = -1;
                int a = 10, b = 20;
                ret = add(a, b);

                printf("The result is: %d\n", ret);

                return 0;
            }
            /******** end **********/

            #####################################
            # File Name: Makefile
            #
            #####################################

            CC = gcc
            LD = gcc

            all:
                    $(CC) mylib.c -g -I. -fPIC -shared -o libmylib.so
                    $(CC) main.c -g -I. -L. -lmylib -o test

            clean:
                    rm *.so test
            #############   END   ###############

                首先將上面的代碼分別存儲到相應(yīng)的目錄,名稱為:mylib.h、mylib.c、main.c、Makefile。

            1)編譯測試代碼。注)編譯時的 -g 選項是必須的。
            [xxx@yyy]$ make
            gcc mylib.c -g -I. -fPIC -shared -o libmylib.so
            gcc main.c -g -I. -L. -lmylib -o t

            通過ls命令我們可以看到生成了測試程序test.
            [xxx@yyy]$ ls
            libmylib.so main.c Makefile mylib.c mylib.h test

            2)執(zhí)行測試程序
            [xxx@yyy]$ ./test
            ./test: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory

            這個錯誤表明程序在運行階段不能找到相應(yīng)的動態(tài)庫文件,此時需要通過環(huán)境變量 LD_LIBRARY_PATH 來指定運行期動態(tài)庫的搜索目錄,我們的動態(tài)庫就在當(dāng)前目錄,如下:

            [xxx@yyy]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

            3)再次執(zhí)行測試程序
            [leo@localhost debug]$ ./test
            Segmentation fault
            [leo@localhost debug]$ ls
            libmylib.so main.c Makefile mylib.c mylib.h test

            4)設(shè)置core文件大小
            Segmentation fault如期而至,但是卻沒有我們更想見到的core文件!
            原來系統(tǒng)在默認(rèn)情況下core文件的大小設(shè)置為0,換句話講也就是不產(chǎn)生core文件。我們可以通過 ulimit 命令來修改core文件的大小,unlimited表示不限制core文件的大小,如下(設(shè)置core文件的大小需要root權(quán)限):
            [root@yyy]# ulimit -c unlimited
            [root@yyy]# ./test
            Segmentation fault (core dumped)
            [root@yyy]# ls
            core.2890 libmylib.so main.c Makefile mylib.c mylib.h test

            5)設(shè)置core文件的格式,輸出路徑
            通過下面命令我們還可以指定core文件的命名格式,路徑等(需要root權(quán)限):
            [root@yyy]# echo "core_%e_%s" >/proc/sys/kernel/core_pattern
            [root@yyy]# ./test
            Segmentation fault (core dumped)
            [root@yyy]# ls
            core.2890 core_test_11.2898 libmylib.so main.c Makefile mylib.c mylib.h test

            6)調(diào)試
            [root@yyy]# gdb test core.2890
            GNU gdb Red Hat Linux (6.5-8.fc6rh)
            Copyright (C) 2006 Free Software Foundation, Inc.
            GDB is free software, covered by the GNU General Public License, and you are
            welcome to change it and/or distribute copies of it under certain conditions.
            Type "show copying" to see the conditions.
            There is absolutely no warranty for GDB. Type "show warranty" for details.
            This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

            Core was generated by `./test'.
            Program terminated with signal 11, Segmentation fault.
            Error while mapping shared library sections:
            libmylib.so: Success.
            Reading symbols from /home/xxx/tst/libmylib.so...done.
            Loaded symbols for libmylib.so
            Reading symbols from /lib/i686/libc.so.6...done.
            Loaded symbols for /lib/i686/libc.so.6
            Reading symbols from /lib/ld-linux.so.2...done.
            Loaded symbols for /lib/ld-linux.so.2
            #0 0x00a8969c in ?? ()
            (gdb)

            鍵入GDB命令 where
            (gdb) where
            #0 0x001ec44c in ?? ()
            #1 0x00000000 in ?? ()

            ?? ()并不是我們想看到的,之所以這樣,是因為GDB不能正確加載我們編寫的動態(tài)庫libmylib.so,我們需要在這里設(shè)置GDB的動態(tài)庫搜索路徑,如下:

            (gdb) set solib-search-path .
            Reading symbols from /home/xxx/test/tst/libmylib.so...done.
            Loaded symbols for /home/xxx/test/tst/libmylib.so
            Reading symbols from /lib/i686/libc.so.6...done.
            Loaded symbols for /lib/i686/libc.so.6
            Reading symbols from /lib/ld-linux.so.2...done.
            Loaded symbols for /lib/ld-linux.so.2

            可以看到GDB已經(jīng)加載了libmylib.so,再次鍵入where命令:
            (gdb) where
            #0 0x001ec44c in add (x=10, y=20) at mylib.c:8
            #1 0x0804847c in main () at main.c:12
            (gdb)

            這次我們期待的結(jié)果出現(xiàn)了,GDB清楚的列出了錯誤出現(xiàn)的位置:mylib.c的第8行,好了,到那里去改code吧!
            posted @ 2010-11-16 10:40 cooelaf 閱讀(1473) | 評論 (0)編輯 收藏

            2008年11月20日

            用戶要想確定在所使用的Linux系統(tǒng)上有沒有加上中文環(huán)境,具體可分為以下兩步來進(jìn)行。
            首先對于bash,需要在/etc/profile或$HOME/.profile文件里加上下面的語句:
            stty cs8 -istrip 
            stty pass8

            執(zhí)行下面的命令:
            #export LANG =C 
            #export LC_CTYPE=iso-8859-1

            然后,在$HOME/.inputrc里加上以下語句:
            set convert -meta off 
            set output -meta on

            修改之后,用戶不必重新啟動系統(tǒng),只需新開一個虛擬終端,或者注銷后再登錄即可生效。

            (轉(zhuǎn)載自http://developer.51cto.com/art/200509/3819.htm)

            posted @ 2008-11-20 08:49 cooelaf 閱讀(1398) | 評論 (0)編輯 收藏

            2008年8月22日

                 摘要: 先簡要介紹dd的參數(shù),后邊通過幾個實例介紹dd的應(yīng)用,參考了其他網(wǎng)友的資料,在此一并感謝 小菜水平有限文中有什么錯誤請大家指正,關(guān)于dd還有什么好的使用方法,可以貼出來,小菜會及時更新 dd 是 Linux/UNIX 下的一個非常有用的命令,作用是用指定大小的塊拷貝一個文件,并在拷貝的同時進(jìn)行指定的轉(zhuǎn)換。 1. 命令簡介 dd&n...  閱讀全文
            posted @ 2008-08-22 09:47 cooelaf 閱讀(469) | 評論 (0)編輯 收藏

            2008年1月27日

                 摘要: 本文列舉了在windows下禁用輸入法的API。  閱讀全文
            posted @ 2008-01-27 16:43 cooelaf 閱讀(1865) | 評論 (0)編輯 收藏

            2007年10月16日

            Technorati 標(biāo)簽: , ,

             

            修改/etc/inittab文件。將id:5:initdefault: 中的5修改為3,表示不進(jìn)入X界面。

            反之亦然。

            posted @ 2007-10-16 18:41 cooelaf 閱讀(437) | 評論 (0)編輯 收藏

            2007年10月10日

                 摘要: 本文介紹了Fedora下Samba服務(wù)器的配置。  閱讀全文
            posted @ 2007-10-10 00:43 cooelaf 閱讀(1319) | 評論 (5)編輯 收藏

            2007年9月27日

                 摘要: 本文介紹了多播編程的要點,不涉及具體代碼。  閱讀全文
            posted @ 2007-09-27 22:29 cooelaf 閱讀(3333) | 評論 (0)編輯 收藏
             
                 摘要: 本文介紹了如何使用Live Writer來寫blog。  閱讀全文
            posted @ 2007-09-27 21:09 cooelaf 閱讀(765) | 評論 (3)編輯 收藏

            2006年5月19日

                 摘要:   閱讀全文
            posted @ 2006-05-19 17:48 cooelaf 閱讀(56187) | 評論 (14)編輯 收藏
            僅列出標(biāo)題  下一頁
             
            久久91精品国产91| 久久亚洲美女精品国产精品| 婷婷久久综合九色综合九七| 亚洲综合熟女久久久30p| 久久精品人人做人人妻人人玩| 国产精品嫩草影院久久| 狠狠综合久久综合88亚洲 | 亚洲综合精品香蕉久久网97| 久久久久亚洲爆乳少妇无| 人妻精品久久久久中文字幕69 | 久久99九九国产免费看小说| 国产成人精品久久免费动漫| 久久午夜夜伦鲁鲁片免费无码影视| 丰满少妇人妻久久久久久| 久久精品国产精品亚洲下载| 国产午夜免费高清久久影院| 久久天天婷婷五月俺也去| 精品欧美一区二区三区久久久 | 久久久久久A亚洲欧洲AV冫| 99久久精品国产高清一区二区 | 青青青青久久精品国产h| 久久精品免费一区二区| 日韩亚洲国产综合久久久| 久久亚洲欧美日本精品| 99精品久久久久中文字幕| 日本欧美久久久久免费播放网| 欧美国产成人久久精品| 一级女性全黄久久生活片免费 | 色偷偷888欧美精品久久久| 久久国产亚洲高清观看| 伊人久久综合精品无码AV专区| 亚洲欧美日韩久久精品| 无码国内精品久久人妻麻豆按摩 | 亚洲AV无码一区东京热久久| 无码人妻久久一区二区三区蜜桃 | 内射无码专区久久亚洲| 久久久久国产一区二区 | 蜜桃麻豆www久久| 久久国产一区二区| 久久综合中文字幕| 国产精品熟女福利久久AV|