2009-04-09 35 views
8

Tôi đang phát triển trên Windows với DevStudio, trong C/C++ không được quản lý.Gọi đến _freea thực sự cần thiết?

Tôi muốn cấp phát một số bộ nhớ trên ngăn xếp thay vì đống vì tôi không muốn phải giải quyết bộ nhớ đó theo cách thủ công (Tôi biết về con trỏ thông minh và tất cả những thứ đó. Tôi có một trường hợp rất cụ thể cấp phát bộ nhớ tôi cần xử lý), tương tự như việc sử dụng các macro A2W() và W2A().

_alloca thực hiện điều đó nhưng không được dùng nữa. Thay vào đó, bạn nên sử dụng malloca. Nhưng tài liệu _malloca nói rằng một cuộc gọi đến ___freea là bắt buộc đối với mỗi cuộc gọi đến _malloca. Sau đó nó đánh bại mục đích của tôi để sử dụng _malloca, tôi sẽ sử dụng malloc hoặc mới để thay thế.

Bất kỳ ai cũng biết nếu tôi có thể thoát khỏi việc không gọi _freea mà không bị rò rỉ và tác động của nội bộ là gì?

Nếu không, tôi sẽ kết thúc bằng cách sử dụng chức năng _alloca không được chấp nhận.

Trả lời

13

Điều quan trọng là phải gọi _freea sau mỗi cuộc gọi đến _malloca.

_malloca giống như _alloca, nhưng thêm một số kiểm tra bảo mật bổ sung và cải tiến để bảo vệ bạn. Kết quả là, có thể cho _malloca phân bổ trên heap thay vì ngăn xếp. Nếu điều này xảy ra, và bạn không gọi _freea, bạn sẽ bị rò rỉ bộ nhớ.

Trong chế độ gỡ lỗi, _malloca ALWAYS phân bổ trên heap, vì vậy cũng nên được giải phóng.

Tìm kiếm _ALLOCA_S_THRESHOLD để biết chi tiết về cách ngưỡng hoạt động và lý do _malloca tồn tại thay vì _alloca và điều đó có ý nghĩa.


Edit:

Đã có ý kiến ​​cho rằng người đó chỉ phân bổ trên heap, và sử dụng con trỏ thông minh vv

Có lợi thế để ngăn xếp phân bổ, mà _malloca sẽ cung cấp cho bạn , do đó, có những lý do để muốn làm điều này. _alloca sẽ làm việc theo cùng một cách, nhưng có nhiều khả năng gây ra một tràn ngăn xếp hoặc vấn đề khác, và tiếc là không cung cấp ngoại lệ tốt đẹp, mà là có xu hướng chỉ xé xuống quá trình của bạn. _malloca an toàn hơn nhiều trong vấn đề này, và bảo vệ bạn, nhưng chi phí là bạn vẫn cần phải giải phóng bộ nhớ của bạn với _freea vì nó có thể (nhưng không có trong chế độ phát hành) mà _malloca sẽ chọn phân bổ trên heap thay vì ngăn xếp.

Nếu mục tiêu duy nhất của bạn là tránh phải giải phóng bộ nhớ, tôi khuyên bạn nên sử dụng một con trỏ thông minh sẽ xử lý việc giải phóng bộ nhớ cho bạn khi thành viên vượt quá phạm vi. Điều này sẽ chỉ định bộ nhớ trên heap, nhưng được an toàn, và ngăn cản bạn phải giải phóng bộ nhớ. Điều này sẽ chỉ làm việc trong C++, mặc dù - nếu bạn đang sử dụng đồng bằng ol 'C, phương pháp này sẽ không hoạt động.

Nếu bạn đang cố gắng phân bổ trên ngăn xếp vì các lý do khác (thường là hiệu suất, vì phân bổ stack rất, rất nhanh), tôi khuyên bạn nên sử dụng _malloca và sống với thực tế là bạn sẽ cần gọi _freea trên giá trị.

+1

Chỉ tò mò, nhưng tại sao các downvotes trên Mitch và bài viết của tôi? Tôi muốn biết tại sao ai đó không đồng ý với bình luận này ... đặc biệt là nếu tôi đang thiếu một cái gì đó. –

1

Để cấp phát bộ nhớ trên ngăn xếp, chỉ cần khai báo biến có loại và kích thước phù hợp.

+0

lý do giảm giá? Các poster được hỏi về ngăn xếp ... –

+0

Nó không phải là downvote của tôi, nhưng tôi đoán chỉ vì anh ta đã yêu cầu cụ thể về _alloca/_malloca, có các mẫu sử dụng chồng rất khác so với các khai báo biến chuẩn. Cá nhân, tôi sẽ bỏ phiếu cho bạn lên, tuy nhiên, bởi vì trong nhiều trường hợp, đây là những gì tôi làm nếu có thể. –

+0

@Reed Copsey: cảm ơn. –

0

Nếu lo ngại của bạn là phải giải phóng bộ nhớ tạm thời và bạn biết tất cả về những thứ như con trỏ thông minh thì tại sao không sử dụng mẫu tương tự khi bộ nhớ được giải phóng khi nó nằm ngoài phạm vi?

template <class T> 
class TempMem 
{ 
    TempMem(size_t size) 
    { 
    mAddress = new T[size]; 
    } 

    ~TempMem 
    { 
    delete [] mAddress; 
    } 

    T* mAddress; 
} 

void foo(void) 
{ 
    TempMem<int> buffer(1024); 

    // alternatively you could override the T* operator.. 
    some_memory_stuff(buffer.mAddress); 

    // temp-mem auto-freed 
} 
3

Một điều cần xem xét là sử dụng một lớp RAII để quản lý việc phân bổ - tất nhiên đó là chỉ hữu ích nếu macro của bạn (hoặc bất kỳ) có thể được hạn chế đến C++.

Nếu bạn muốn tránh nhấn heap vì lý do hiệu suất, hãy xem kỹ thuật được sử dụng bởi lớp mẫu auto_buffer<> của Matthew Wilson (http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html). Điều này sẽ phân bổ trên stack trừ khi yêu cầu kích thước thời gian chạy của bạn vượt quá kích thước được chỉ định tại thời gian trình biên dịch - vì vậy bạn nhận được tốc độ phân bổ heap cho phần lớn phân bổ (nếu bạn định kích thước mẫu), nhưng mọi thứ vẫn hoạt động chính xác nếu bạn vượt quá kích thước đó.

Kể từ STLSoft có một toàn bộ rất nhiều cruft để đối phó với vấn đề tính di động, bạn có thể muốn xem xét một phiên bản đơn giản của auto_buffer<> được mô tả trong cuốn sách của Wilson, "Imperfect C++".

tôi thấy nó khá tiện dụng trong một dự án nhúng .

+1

+1 trên đề xuất auto_buffer <>. Nó là cơ bản làm những gì _malloca không thay vì _alloca trên cửa sổ. Có một kiểm tra để chắc chắn rằng bạn sẽ không thổi giới hạn stack của bạn, và nó sẽ làm phân bổ đống nếu cần thiết thay vì phân bổ stack. Điều này hoạt động trong C, mặc dù, quá. –

1

Tôi đã trả lời câu hỏi này trước đây, nhưng tôi đã bỏ lỡ một số điều cơ bản có nghĩa là nó chỉ hoạt động ở chế độ gỡ lỗi. Tôi đã chuyển cuộc gọi tới _malloca thành hàm tạo của lớp sẽ tự động miễn phí.

Trong gỡ lỗi này là tốt, vì nó luôn luôn phân bổ trên heap. Tuy nhiên, trong bản phát hành, nó phân bổ trên ngăn xếp, và khi trở về từ hàm tạo, con trỏ ngăn xếp đã được đặt lại và bộ nhớ bị mất.

Tôi quay lại và thực hiện một cách tiếp cận khác, dẫn đến kết hợp sử dụng macro (eurgh) để cấp phát bộ nhớ và khởi tạo một đối tượng sẽ tự động gọi _freea trên bộ nhớ đó. Vì nó là một macro, nó được cấp phát trong cùng một khung ngăn xếp, và vì vậy sẽ thực sự hoạt động trong chế độ phát hành. Nó chỉ là thuận tiện như lớp học của tôi, nhưng hơi ít tốt đẹp để sử dụng.

tôi đã làm như sau:

class EXPORT_LIB_CLASS CAutoMallocAFree 
{ 
public: 
    CAutoMallocAFree(void *pMem) : m_pMem(pMem) {} 
    ~CAutoMallocAFree() { _freea(m_pMem); } 

private: 
    void *m_pMem; 

    CAutoMallocAFree(); 
    CAutoMallocAFree(const CAutoMallocAFree &rhs); 
    CAutoMallocAFree &operator=(const CAutoMallocAFree &rhs); 
}; 

#define AUTO_MALLOCA(Var, Type, Length) \ 
    Type* Var = (Type *)(_malloca((Length) * sizeof (Type))); \ 
    CAutoMallocAFree __MALLOCA_##Var((void *) Var); 

Bằng cách này tôi có thể phân bổ sử dụng các cuộc gọi vĩ mô sau, và nó được phát hành khi lớp được thuyết minh đi ra khỏi phạm vi:

  AUTO_MALLOCA(pBuffer, BYTE, Len); 
      Ar.LoadRaw(pBuffer, Len); 

lời xin lỗi của tôi cho đăng tải cái gì đó rõ ràng là sai!

0

Nếu bạn đang sử dụng _malloca() thì bạn phải gọi _freea() để ngăn rò rỉ bộ nhớ vì _malloca() có thể thực hiện phân bổ trên stack hoặc heap. Nó sẽ phân bổ trên heap nếu kích thước đã cho vượt quá giá trị_ALLOCA_S_THRESHOLD. Vì vậy, an toàn hơn để gọi _freea() sẽ không làm bất cứ điều gì nếu phân bổ xảy ra trên stack.

Nếu bạn đang sử dụng _alloca() dường như không được dùng nữa kể từ hôm nay; không cần phải gọi số _freea() khi phân bổ xảy ra trên ngăn xếp.

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