2011-08-14 25 views
7

Khi gỡ lỗi với GDB, tôi muốn đặt một biến tiện lợi thành giá trị mới được xây dựng.Cách gọi hàm tạo trong gdb cho các máy in đẹp

Tôi đang lập trình bằng cách sử dụng khung Qt, vì vậy tôi muốn tạo một QString, nhưng điều này không liên quan đến câu hỏi, vì tôi muốn biết cách làm điều này với bất kỳ lớp nào.

tôi đã cố gắng

(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")'. 

sau đó tôi cố gắng sử dụng set overload-resolution off, kết quả như sau:

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. 

Vì vậy, tôi cho rằng một con trỏ này là cần thiết:

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

Được rồi, nhà thầu return void, điều đó có nghĩa là tôi phải lưu giá trị trả về của malloc ở đâu đó:

(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" 

Được rồi, bây giờ điều này hoạt động như mong đợi, tuy nhiên tôi muốn sử dụng mã này trong gdb.parse_and_eval() cho máy in đẹp trăn. Bây giờ điều này sẽ gọi malloc rất nhiều lần, tạo ra một rò rỉ bộ nhớ. Vì vậy, chỉ cần gọi miễn phí()? Hiện tại, điều bất ngờ xảy ra:

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

Con trỏ vẫn có vẻ hợp lệ, vì bộ nhớ không được sử dụng lại. Tuy nhiên tôi không chắc liệu điều này có ổn không vì sau khi phân bổ thêm một vài khối bộ nhớ phù hợp với chính xác một giá trị con trỏ QString vẫn chưa được sử dụng lại bởi malloc.

Tôi có tạo ra rò rỉ bộ nhớ lớn nếu tôi sử dụng nó trong một máy in khá hay, có thể được gọi rất nhiều lần trong một phiên gỡ lỗi? Có giải pháp nào dễ dàng hơn trong việc tạo kết quả mong muốn (tức là sử dụng API Python) không?

Cũng không liên quan đến điều này, tại sao miễn phí (3) cho tôi giá trị trả lại là 0 trong khi thực sự bị vô hiệu?

Trả lời

1

Tôi không biết cách giải phóng con trỏ. Nó có vẻ là không thể, nhưng rò rỉ bộ nhớ được tạo nên khá nhỏ. Nhưng tôi biết cách xóa hiệu ứng mà bạn mô tả là

Con trỏ vẫn có vẻ hợp lệ, vì bộ nhớ không được sử dụng lại. Tuy nhiên tôi không chắc liệu điều này có ổn không vì sau khi phân bổ thêm một vài khối bộ nhớ phù hợp với chính xác một giá trị con trỏ QString vẫn chưa được sử dụng lại bởi malloc.

Xem mã này mà sẽ hiển thị như thế nào người ta có thể giải quyết vấn đề (chỉ thử nghiệm trên 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 = "" 

Lý do tại sao phiên bản của bạn không thể giải phóng bộ nhớ là lệnh miễn phí của bạn chỉ ảnh hưởng đến bộ nhớ được đặt trước trực tiếp (ví dụ:các con trỏ và các kiểu cơ bản được định nghĩa bởi lớp), không phải là đối tượng được tạo (nghĩa là bộ nhớ được đặt bởi hàm tạo và các phương thức của đối tượng mà bạn có thể gọi).

Trước tiên, bạn cần gọi hàm hủy của đối tượng đã tạo và sau đó giải phóng con trỏ (dòng dưới $ 2 trong mã của tôi).

Khi dòng cuối cùng ($ 5) mã của tôi ngụ ý máy in đẹp của gdb có thể khôi phục nội dung của đối tượng ngay cả khi bộ nhớ của đối tượng không còn bị chiếm đóng bởi quá trình. Lý do có thể là máy in có thể thực hiện điều này với gần như mọi địa chỉ bộ nhớ và khi không có quá trình nào khác ghi vào nơi này (chúng tôi đã chiếm một vài giây trước đó), chúng tôi sẽ nhận được kết quả tương tự như khi không được gọi miễn phí.

PS: Định dạng của trình phá hủy và cảnh báo sẽ cho bạn thấy rằng có một chút khó khăn khi tìm đúng biểu thức của trình phá hủy. Tôi không có dự án QT-Project thực tế để thử điều này với QString, nhưng nó phải khá gần mà tôi đã làm.

1

Bạn đang cố gắng làm gì? Nếu bạn muốn in ấn một QString với gdb, hãy sử dụng API máy in Python khá của gdb. Xem http://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html để biết chi tiết. Bạn có thể sử dụng lớp máy in Python như sau:

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'