2012-05-22 60 views
7

Tôi đã bắt đầu một dự án trong C++. Quản lý bộ nhớ bằng ngôn ngữ này là mới đối với tôi.Kỹ thuật quản lý bộ nhớ C++/Thực tiễn

Tôi đã sử dụng để tạo đối tượng với new() và sau đó vượt qua xung quanh con trỏ và trong khi nó hoạt động, đó là một nỗi đau để gỡ lỗi và mọi người nhìn tôi buồn cười khi họ nhìn thấy mã. Tôi khá tự hào về thực tế rằng nó không bị rò rỉ hoặc segfault (một lần cố định), nhưng nó thực sự là rất nhiều nỗ lực.

list <struct Connection *> users; 

struct Connection * accept_connection (const char *name) { 
    struct Connection * new_node = new Connection(); 
    new_node->_data = ... // whatever, set it up here 
    return new_node; 
} 

struct Connection * new_user = accept_connection (const char *name); 
users.append (new_user); 

Vì vậy, tôi có một chiến lược mới cho phiên bản tiếp theo của dự án. Cho đến nay những gì tôi đang làm là tạo ra các đối tượng với new() và gán cho chúng một số ID nguyên duy nhất. Sau đó, tôi lưu trữ đối tượng trong bảng băm bằng cách sử dụng ID làm khóa. Bây giờ các mục được lưu trữ và truyền xung quanh bởi số ID nguyên và khi bạn cần phải de-tham chiếu nó, bạn đi đến bảng băm và nó trả về cho bạn hoặc thing * hoặc NULL. Do đó tôi không còn gặp lỗi con trỏ nhưng tốc độ của mã được giảm một chút.

typedef unsigned long ID_Number; 

// create a user and return the ID 
ID_Number create_user() { 
    ID_Number new_id = assign_unique_id(); 
    struct User * node = new User(); 
    node->_id = new_id; 
    node->_data = ... // whatever, set it up here 
    add_to_users_dict (new_id, node); 
    return new_id; 
} 

list <ID_Number> users; 

for_each (users.begin(), users.end(), process_user); 

void process_user (ID_Number i) { 
    struct User * u_ptr = lookup_user_dict (i); 
    if (u_ptr == NULL) { 
    // not found in dict 
    // somehow this guy was deleted 
    } else { 
    // we can do stuff with this guy 
    } 
} 

Bây giờ tôi đã quen thuộc với nguyên lý cơ bản của lập trình nhưng là một người có sở thích tự học, tôi không quen thuộc với các thực tiễn và công cụ của ngành. Những gì tôi về cơ bản yêu cầu, là hướng dẫn về quản lý bộ nhớ:

1) Tôi đang làm gì đúng hay sai?

2) Có bất kỳ gói hoặc thư viện nào tôi có thể sử dụng sẽ giúp tôi không?

3) Thực tiễn tiêu chuẩn của ngành là gì?

4) Về cơ bản tôi nên googling hoặc mua cho kindle vv?

Hôm nay tôi thường sử dụng Python, nó xử lý nhiều thứ "back end" cho tôi, nhưng tôi cần C hoặc C++ (tôi đoán mình đang sử dụng đồng bằng C cộng với stdC++ libs, tôi không chắc lắm Sự trùng lặp giữa các ngôn ngữ là - tôi chỉ biết g ++ biên dịch tốt) cho một dự án cụ thể vì lý do tốc độ/hiệu suất: mặc dù tôi nghi ngờ một số thiên tài toán học có thể cung cấp các bản sửa lỗi thuật toán để tăng tốc, mặc dù đó là một câu hỏi riêng.

+2

Bắt đầu bằng cách xem 'shared_ptr'. –

+0

Công cụ đầu tiên tôi sử dụng là valgrind: http://valgrind.org/docs/manual/QuickStart.html – Anycorn

+10

Tra cứu RAII. Điều này thật điên rồ. –

Trả lời

5

Câu trả lời hay nhất tôi có thể đưa ra, là bạn không nên sử dụng con trỏ theo cách truyền thống. C++ 11 đã thay đổi cách lập trình giao dịch với quản lý bộ nhớ.

Thay vì giải thích những điều đã được giải thích chi tiết bởi những người thông minh hơn tôi nhiều, tôi sẽ chỉ cung cấp một số liên kết.

Đầu tiên bạn nên xem xét là Herb Sutter Điều Elements of Modern C++ Style Sau đó kiểm tra xem video của Bjarne Stroustrup C++11 Style

Nếu bạn có thể sử dụng các tiêu chuẩn mới C++ 11 bạn nên, nó làm cho quản lý bộ nhớ nhiều sạch hơn trước.

+2

Và nếu bạn không thể sử dụng C++ 11 (gọi headhunter của bạn!), Có rất nhiều thứ để không quản lý bộ nhớ theo cách thủ công trên mạng hoạt động với C++ 03. –

1

1) Tôi đang làm gì đúng hay sai?

Bạn không sử dụng thành ngữ Resource Acquisition Is Initialization (RAII) hoặc ngữ nghĩa quyền sở hữu C++ hiện đại.

2) Có gói hoặc thư viện nào tôi có thể sử dụng để trợ giúp tôi không?

Nếu bạn thực sự cần truyền con trỏ xung quanh, bạn có thể sử dụng lệnh std :: unique_ptr và std :: shared_ptr. Nhưng trước khi đi đến đó bạn nên tìm hiểu về việc làm cho các đối tượng của riêng bạn hoạt động như các chủ sở hữu tài nguyên với ngữ nghĩa RAII.

3) Thực tiễn tiêu chuẩn của ngành là gì?

4) Về cơ bản tôi nên googling hoặc mua cho kindle vv?

RAII

2

Tôi đang làm gì đúng hay sai?

Về cơ bản, bạn đã tạo một hệ thống sử dụng tay cầm để tham chiếu đến đối tượng thay vì con trỏ trực tiếp. Điều này có thể thích hợp cho một số tình huống. Các hệ điều hành thường sử dụng các chốt điều khiển khi hệ điều hành "sở hữu" đối tượng và quản lý thời gian của nó nhưng cho phép một máy khách tham chiếu đến nó.

Có bất kỳ gói hoặc thư viện nào tôi có thể sử dụng sẽ giúp tôi không?

Thư viện chuẩn trong C++ hiện đại có shared_ptr và unique_ptr, là con trỏ thông minh quản lý tuổi thọ của đối tượng động. Họ là một cách tuyệt vời để sử dụng RAII.

Thực tiễn tiêu chuẩn của ngành là gì?

Tiêu chuẩn thực tế trong C++ là RAII - phân bổ tài nguyên là khởi tạo. Quan hệ RAII phân bổ cho các nhà xây dựng và deallocation đến destructors. Vì C++ có bảo đảm vững chắc về cách thức và khi c'tors và d'tors thực hiện, điều này mang đến cho bạn một cách hoàn hảo để quản lý các vòng đời của đối tượng mà không bị rò rỉ. Các con trỏ thông minh, shared_ptr và unique_ptr, cũng làm cho quyền sở hữu của đối tượng rõ ràng.

Về cơ bản, tôi nên googling hoặc mua cho kindle vv?

Tìm kiếm RAII.

1

Lỗi đầu tiên của bạn là sử dụng new.

Bộ nhớ động hiếm khi cần thiết và thậm chí còn hiếm hơn khi cần "trực tiếp": hầu hết các đối tượng được phân bổ động nằm trong một vùng chứa (như vector hoặc map). Lỗi thứ hai của bạn không phải là sử dụng các hàm tạo, khi bạn hiểu các biến thể lớp là gì và cách các nhà xây dựng kích hoạt chúng, thì bạn sẽ có thể tận dụng RAII (Khởi tạo tài nguyên là khởi tạo) và dừng mã hóa trong C.

+0

Tôi bắt đầu nhìn vào RAII - quấn ctor/dtor để dtor được tự động gọi khi trình bao bọc được lấy ra khỏi ngăn xếp. Vì vậy, với RAII làm thế nào để tôi đặt một trường hợp duy nhất của một điều vào hai danh sách khác nhau? Tôi phải sử dụng tài liệu tham khảo? Làm thế nào sau đó tôi dừng danh sách B từ iterating trên một cái gì đó danh sách A cho biết để xóa? Có vẻ như tôi sẽ phải thêm một boolean "is_deleted_skip_me" vào mỗi cấu trúc (và chọn chúng theo định kỳ) hoặc tôi cần phải tiếp tục xóa danh sách của mình bất cứ khi nào có bất kỳ danh sách nào thay đổi? - EDIT: Tôi bắt đầu nghĩ rằng các ứng dụng được thiết kế kém nếu nó cần rất nhiều danh sách riêng biệt. – gecko

+0

@gecko: nhiều danh sách phụ thuộc lẫn nhau có vẻ xấu, mặc dù tôi không biết các ràng buộc của bạn. Bạn không thể sao chép thông tin sao cho mỗi danh sách có bản sao của riêng nó? Nếu không, luôn luôn có khả năng sử dụng một 'shared_ptr', nhưng nó mở cửa cho một số khó khăn xuống đường. –

+0

Hộp (đối tượng dữ liệu) bên trong một vùng chứa (chính nó là một thể hiện khác nhau của cùng một cấu trúc - chỉ tên và dung lượng khác nhau), vì vậy vùng chứa có một danh sách các nội dung của nó. Một tác nhân nhớ lại N mục cuối cùng mà nó chạm vào. Vì vậy, nếu một tác nhân đặt các hộp vào một vùng chứa, đó là 2 danh sách có cùng các mục. – gecko

Các vấn đề liên quan