2011-08-14 88 views
7

使用GDB進行調試時,我想將便捷變量設置爲新構造的值。如何在gdb中爲漂亮打印機調用構造函數

我使用Qt框架編程,所以我想創建一個QString的,但是這是風馬牛不相及的問題,因爲我想知道如何與任何類做到這一點。

我試圖

(gdb) set $str = 'QString::QString("abc")' 
No symbol "QString::QString("abc")" in current context. 

(gdb) set $str = QString::QString("abc") 
Cannot resolve method QString::QString to any overloaded instance 

(gdb) set $str = QString("abc") 
A syntax error in expression, near `("abc")'. 

然後我嘗試使用set overload-resolution off,導致以下:

set $str = QString::QString("abc") 
non-unique member `QString' requires type instantiation 

set $str = 'QString::QString(const char*)'("abc") 
Too few arguments in function call. 

所以我假定一個需要此指針:

(gdb) set $str = 'QString::QString(const char*)'(malloc(sizeof(QString)), "abc") 
(gdb) p $str 
$8 = void 

好,構造返回void,這意味着我必須將malloc的返回值保存在某處:

(gdb) set $pointer = malloc(sizeof(QString)) 
(gdb) p $pointer 
$9 = 6304560 
(gdb) p/x $pointer 
$10 = 0x603330 
(gdb) set $str = 'QString::QString(const char*)'($pointer, "abc") 
(gdb) p $str 
$11 = void 
(gdb) p $pointer 
$12 = 6304560 
(gdb) p *((QString*)$pointer) 
$13 = "abc" 

好了,現在可正常工作,但是我想使用此代碼gdb.parse_and_eval()的巨蟒漂亮的打印。現在這會調用malloc很多次,造成內存泄漏。所以,只需撥打免費()?現在,意想不到的事情發生:

(gdb) call free($pointer) 
$14 = 0 
(gdb) p *((QString*)$pointer) 
$15 = "abc" 

指針似乎仍然有效,當然,這可能是完全正常的,因爲內存沒有得到重用。不過,我不確定這是否可行,因爲在分配了幾個更符合一個QString的內存塊之後,指針值仍然沒有被malloc重用。

我是不是創建一個大的內存泄漏,如果我用這個在一個漂亮的打印機,這很可能在調試會話期間被調用很多次?有沒有更容易的解決方案來創建所需的結果(即使用Python API)?

也無關這一點,爲什麼是免費的(3)給我的返回值爲0,而它實際上是無效?

回答

1

我不知道如何釋放指針。這似乎是不可能的,但創建的內存泄漏應該很小。但我知道如何去除你所描述的效果

指針看起來仍然有效,當然這可能是完美的,因爲內存還沒有被重用。但是我不能確定這是否是可以的,因爲它分配完全適合一個即QString指針值仍未通過的malloc重用的幾個內存塊之後。

看到這個代碼,應該表現出一個如何能解決這個問題(僅適用於GNU GDB試驗(GDB)SUSE(7.5.1-2.1.1))

(gdb) call malloc(sizeof(std::string)) 
$1 = (void *) 0x64e4d0 
(gdb) call ((std::string*)0x64e4d0)->basic_string() 
(gdb) call ((std::string*)0x64e4d0)->assign("Hello World") 
$2 = "Hello World" 
(gdb) call ((std::string*)0x64e4d0)->'~basic_string'((std::string*)0x64e4d0) 
warning: Using non-standard conversion to match method std::string::~basic_string to supplied arguments 
(gdb) print ((std::string*)0x64e4d0) 
$3 = (std::string *) 0x64e4d0 
(gdb) print *((std::string*)0x64e4d0) 
$4 = "" 
(gdb) call free(0x64e4d0) 
(gdb) print *((std::string*)0x64e4d0) 
$5 = "" 

之所以你的版本無法釋放內存的原因是您的免費命令只會影響直接保留內存(例如,由類定義的指針和基本類型),而不是創建的對象(意思是由構造函數保留的內存以及可能調用的對象的方法)。

需要先調用創建對象的析構函數,然後釋放指針(我的代碼中的$ 2以下的行)。

由於我的代碼的最後一行($ 5)意味着gdb的漂亮打印機能夠恢復對象的內容,即使對象的內存不再被進程佔用。原因可能是打印機可以在幾乎每個內存地址都做到這一點,當沒有其他進程向這個地方寫入數據(我們之前已經佔用了數秒)時,我們會得到與未調用free時相同的結果。

PS:析構函數的格式和警告應該會告訴你找到正確的析構函數表達式有點棘手。我沒有真正的QT項目來與QString一起嘗試這個,但它應該非常接近我所做的。

1

你想做什麼?如果你想用gdb漂亮地打印一個QString,使用gdb的Python漂亮的打印機API。詳情請參閱http://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html。您可以使用類似以下的Python打印機類:

class QStringPrinter: 
    def __init__(self, val): 
     self.val = val 

    def to_string(self): 
     if self.val['d'] == self.val['shared_null'].address: 
      return 0 

     dataptr = self.val['d']['data'].cast(gdb.lookup_type('char').pointer()) 
     size = self.val['d']['size'] 

     if sys.byteorder == 'little': 
      enc = 'utf_16_le' 
     else: 
      enc = 'utf_16_be' 
     return dataptr.string(enc, 'ignore', size * 2) 

    def display_hint(self): 
     return 'string'