2012-05-17 21 views
6

Tôi đang cố gắng tìm hiểu gtkmm và quyết định thử gtkmm 2.4 trong thời gian này vì có vẻ như rất khó để có được 3.0 làm việc trên Debian. Dù sao, ví dụ tôi đang cố gắng là một ở đây: http://developer.gnome.org/gtkmm-tutorial/2.24/sec-helloworld.html.en. Nó biên dịch tốt và nó chạy là tốt không sao, nhưng khi tôi đóng nó valgrind báo cáo rất nhiều rò rỉ, một cái gì đó dọc theo dòng này (sau khi nhấp vào nút một lần):gtkmm/C++ bộ nhớ rò rỉ ví dụ thế giới đầu tiên

==4254== Memcheck, a memory error detector 
==4254== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. 
==4254== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==4254== Command: ./bin/jmb 
==4254== 
Hello World 
==4254== 
==4254== HEAP SUMMARY: 
==4254==  in use at exit: 942,940 bytes in 7,968 blocks 
==4254== total heap usage: 14,191 allocs, 6,223 frees, 3,272,961 bytes allocated 
==4254== 
==4254== LEAK SUMMARY: 
==4254== definitely lost: 2,620 bytes in 6 blocks 
==4254== indirectly lost: 5,936 bytes in 187 blocks 
==4254==  possibly lost: 358,625 bytes in 1,775 blocks 
==4254== still reachable: 575,759 bytes in 6,000 blocks 
==4254==   suppressed: 0 bytes in 0 blocks 
==4254== Rerun with --leak-check=full to see details of leaked memory 
==4254== 
==4254== For counts of detected and suppressed errors, rerun with: -v 
==4254== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 9 from 9) 

Điều này xảy ra nếu tôi dừng lại chương trình với Cc hoặc nhấp vào nút đóng cửa sổ (trong trường hợp này tôi phải sử dụng Shift-Meta-C để đóng cửa sổ vì trình quản lý cửa sổ). Đây có phải là hành vi mong đợi như trình kết nối của MySQL không cho phép bạn xóa một con trỏ cuối cùng không? Trong trường hợp đó, có vẻ như rất nhiều bộ nhớ không bị "cho phép" xóa? Hoặc tôi chỉ thiếu một cái gì đó thực sự đơn giản?

Vì lợi ích của nó ở đây là mã của tôi: (Thay đổi HelloWorld để Test) main.cpp:

#include "gui/Test.hpp" 
#include <gtkmm/main.h> 
int main(int argc, char **argv) 
{ 
    Gtk::Main kit(argc, argv); 
    Test t; 
    Gtk::Main::run(t); 
    return 0; 
} 

Test.hpp:

#pragma once 

#include <gtkmm/button.h> 
#include <gtkmm/window.h> 

class Test 
    : public Gtk::Window 
{ 
public: 
    Test(); 
    virtual ~Test(); 

protected: 
    //Signal handlers: 
    void on_button_clicked(); 

    //Member widgets: 
    Gtk::Button m_button; 
}; 

Test.cpp:

#include "Test.hpp" 
#include <iostream> 

Test::Test() 
    : m_button("Hello World") // creates a new button with label "Hello World". 
{ 
    // Sets the border width of the window. 
    set_border_width(10); 

    // When the button receives the "clicked" signal, it will call the 
    // on_button_clicked() method defined below. 
    m_button.signal_clicked().connect(sigc::mem_fun(*this, 
       &Test::on_button_clicked)); 

    // This packs the button into the Window (a container). 
    add(m_button); 

    // The final step is to display this newly created widget... 
    m_button.show(); 
} 

Test::~Test() 
{ 

} 

void Test::on_button_clicked() 
{ 
    std::cout << "Hello World" << std::endl; 
} 

Cảm ơn trước!

+0

Không phải là câu trả lời đúng cho câu hỏi gtk của bạn, nhưng nói chung khi điều tra rò rỉ bộ nhớ, hãy sử dụng 'valgrind --leak-check = full -leak-resolution = high --track-origins = yes' để biết thêm chi tiết. –

+0

cung cấp cho tôi quá nhiều thông tin để có thể xử lý nó. tôi nên thêm một liên kết đến đầu ra? – lfxgroove

+1

Tôi đề nghị bạn kiểm tra nó một cách cẩn thận và hiểu nó, nó sẽ hữu ích và một bài tập có giá trị sẽ giúp bạn trong tương lai. Một người khác có thể giải thích nó cho bạn nhưng nếu họ có thể làm điều đó thì bạn cũng vậy. Bạn có thể loại bỏ '--leak-resolution = high' để giảm đầu ra, nếu điều đó có ích. –

Trả lời

3

Sự rò rỉ không phải từ mã của bạn, vì bạn không có phân bổ bộ nhớ động. Vì bạn đã xác định biến số Test t trên ngăn xếp và không tự động, nó sẽ bị xóa khi nó nằm ngoài phạm vi. Điều đó sẽ xảy ra khi hàm main() hoàn thành, trước khi toàn bộ chương trình hoàn thành. Lớp Kiểm tra cũng không có bất kỳ phân bổ bộ nhớ động nào trực tiếp. Bằng cách đề cập trực tiếp, tôi có nghĩa là trực tiếp trong lớp đó, nhưng không có trong thuộc tính (gtk, vv) nó chứa.

Để chứng minh rằng trường hợp Kiểm tra của bạn thực sự bị xóa, bạn có thể đặt printf vào trình hủy. Bạn sẽ thấy đầu ra khi ứng dụng thoát.

Thậm chí nếu bạn đã định nghĩa/tạo Test dụ tự động, bạn sẽ nhận được vào các thói quen của luôn xóa tất cả mọi thứ bạn tạo ra. Trong trường hợp này chỉ là bộ nhớ của nó, nhưng nó có thể là tài nguyên có giá trị hơn như kết nối DB, tài nguyên Hệ thống tệp hoặc một số logic khác cần được thực hiện khi thoát.

Có thể cho Valgrind cung cấp cho bạn dấu vết ngăn xếp nơi rò rỉ bộ nhớ thực sự xảy ra, Im khá chắc chắn bạn sẽ thấy rằng chúng đang ở trong mã gtk. Nếu vậy, tôi sẽ xem xét việc nuôi một con bọ. Tôi sẽ không quá lo lắng về bộ nhớ still reachable (nó không thực sự là một rò rỉ), nhưng thay vì nhìn vào definitely lostindirectly lost.

+0

Bạn có thể giải thích lý do tại sao vẫn có thể truy cập không phải là sự rò rỉ thực sự hoặc chỉ cho tôi một số tài nguyên về lý do tại sao? Ngoài ra, tôi đã chạy Valgrind với --show-origin = yes và nó cho thấy hầu hết các gtk mà còn là cairo và pango, tôi có nên báo cáo lỗi ở đó không? Cảm ơn trước! – lfxgroove

+0

@Anton, rò rỉ bộ nhớ là bộ nhớ mà bạn không còn quyền truy cập, nghĩa là bạn đã có con trỏ vào bộ nhớ, sau đó không giải phóng bộ nhớ, bạn chỉ định giá trị khác cho con trỏ, do đó "mất" địa chỉ của nó. Bộ nhớ vẫn có thể truy cập là bộ nhớ vẫn được tham chiếu bởi một con trỏ và chương trình chấm dứt, do đó bộ nhớ không bị "mất". Đối với các lỗi, tôi sẽ nói có, nhưng có thể là gtk không quản lý đúng các thư viện đó, vì vậy chúng có thể từ chối nó. Khi bạn tập tin lỗi, hiển thị các ngăn xếp Valgrind, họ sẽ đánh giá cao nó :) – Brady

+0

@Anton, tôi nên đề cập đến rằng "vẫn tiếp cận" không nghiêm trọng như rò rỉ, nhưng lý tưởng nó vẫn nên được giải quyết. – Brady

1

Đặt biến môi trường G_SLICE để định cấu hình lại bộ cấp phát bộ nhớ GSlice.

G_SLICE=always-malloc ./your_application 

Nhìn vào this post để biết chi tiết.

+0

Tôi đã thử cả G_SLICE = always-malloc và G_DEBUG = gc-friendly [, resident-modules] nó không giúp được gì nhiều, tải xuống tệp nén đã đề cập, nó đã loại bỏ một số lỗi. – lfxgroove

2

Giả sử Gtk-- không bị rò rỉ bộ nhớ, kết quả bạn đăng có thể tương thích với giả định này.

Thực tế là một số bộ nhớ vẫn có thể truy cập được khi thoát khỏi chương trình không giống như rò rỉ bộ nhớ.

Chương trình sau có bị rò rỉ bộ nhớ không?

int main() { 
    int* a = new int[10]; 
    return 0; 
} 

Có vẻ như vậy, nhưng câu trả lời hoàn chỉnh phải là: Phụ thuộc!

Nếu chúng ta không sử dụng MS/DOS và "a" là cần thiết cho đến cuối chương trình, điều này khó có thể xác định rò rỉ ... chúng ta có thể nói rằng lập trình viên có trách nhiệm dọn dẹp hệ điều hành cơ bản.

Hơn nữa Valgrind là một công cụ rất tốt và hữu ích, nhưng có thể báo cáo dương tính giả.

+0

Vì vậy, những gì bạn đang nói là họ không thể/sẽ không làm sạch những phần cuối cùng của bộ nhớ và để lại cho os cơ bản? Có loại tài liệu nào về điều này không? Ngoài ra, đó là bình thường? – lfxgroove

+0

Tôi đã đưa ra nhận xét chung, tôi không thể nói cho các nhà phát triển gtkmm. Tôi nghĩ rằng nơi thích hợp để hỏi những gì họ dự định làm là danh sách gửi thư của họ. – baol