Có cần phải delete pointer point đến unknown block?

c++

(Red Sand) #1

Mình có pointer ptr point đến first element của vector data, tức ptr =& data[0].
Theo mình biết memory cho vector data tự được giải phóng khi vector out of scope.
Mình thử delete ptr thì bị trigger break point ptr point to unknown block. Vậy có nghĩa là block chứa data[0] đã được giải phóng? Mình có cần phải giải phóng 32 bit chứa địa chỉ của pointer ptr nữa không?


(Phạm Vinh) #2

Có thể bạn nhầm lẫn giữa Stack Memory và Heap Memory. Khi các biến được khởi tạo trong Stack, chúng đều sẽ được giải phóng khi out of scope. Nhưng với những biến trong Heap (khai báo bằng từ khóa new) ta không thể làm điều tương tự mà phải tự giải phóng thông thường. Vậy nên để chốt lại, bạn hãy xem biến của mình được lưu trong vùng nhớ nào của chương trình khi quyết định có nên giải phóng không.
Mong là mình nói dễ hiểu

p/s: Bạn có thể tham khảo thêm ở https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html


(Red Sand) #3

Mình khá chắc là vùng nhớ mà pointer trỏ đến đã được giải phóng. Vì vùng nhớ đó lúc mình khởi tạo kiểu thông thường là: std::vector(). Quan sát debugger sau khi vector data bị out of scope hoặc bị delete thì pointer ptr trỏ đến vùng không xác định.
Sau đó mình có phải viết đoạn ptr = nullptr để giải phóng nốt 4 bytes mà ptr dùng để lưu địa chỉ hay không.
Cụ thể int* ptrstd::vector<int> data nằm trong cùng 1 class, ptr trỏ đến data[0]. Mặc định destructor sẽ giải phóng data rồi. Mình thắc mắc lúc này chuyện gì sẽ sảy ra với ptr, nó còn hold phần bộ nhớ data[0] không? Nếu không còn thì 4 bytes chứa địa chỉ của bản thân ptr có được tự động giải phóng luôn theo destruction không?


(‏) #4

ko, nó trỏ tới 1 ngôi nhà hoang vô chủ, vô ở nhà hoang có ngày gặp ma (bị crash) ráng chịu

có, vì ptr thuộc object của class đó, nếu object đó nằm trên stack, sẽ được xóa khi object đó out of scope

nói nôm na anh data đi thuê nhà của OS, OS cung cấp cho data 1 căn nhà ở địa chỉ X. data cho ptr địa chỉ X của nhà mình thuê. Sau khi xài xong data trả nhà cho OS, OS lấy nhà lại, nhưng ptr vẫn còn địa chỉ X của data trước đó. Hỏi "ptr có còn hold căn nhà thuê của data ko?" thì nó có thuê nhà bao giờ đâu mà nó hold :V “hold” nghĩa là sao?? Nó có cái địa chỉ đó nhưng địa chỉ đó đã hết được data thuê thì chả làm gì, khi giải phóng cũng chả cần gán nullptr cho ptr làm gì.

mà với std::vector thì ko nên lưu giá trị &data[0] xuống 1 biến tồn tại “lâu” làm gì, vì nó có thể bị invalidated khi vector thêm phần tử mới, thay đổi kích thước. Khi thay đổi kích thước có thể data sẽ phải di chuyển toàn bộ mảng cũ sang mảng mới ở địa chỉ mới, nên lưu vào 1 biến ptr tồn tại “lâu” tới sau khi vector được push back thêm mấy phần tử thì khi sử dụng ptr có thể vẫn còn trỏ tới địa chỉ cũ, ko đúng @_@


(Red Sand) #5

Mình hiểu rồi, vậy là ptr chỉ trỏ tới chứ k allocate block đó.
Mình lưu &data[0] vào ptr là có chủ đích, chỉ hơi khó quản lý chút, đã bị cái bug ptr trỏ tới địa chỉ “nhà ma” sau khi object out of scope. Sau phải định nghĩa lại copy constructor.

Mình thắc mắc nhất là cái này, tks bạn!


(‏) #6

có thể bị invalidate khi data có xài push_back đó. Khi nào cần &data[0] thì gọi hẳn &data[0] luôn chứ đừng store vào 1 cái ptr nào đó.

ví dụ data ban đầu là mảng 8 phần tử, capacity 8 phần tử, địa chỉ &data[0] là 0x1100, push_back thêm 1 phần tử thì data tăng gấp đôi capacity lên, hay mảng cũ bị dời sang mảng mới có size 9 phần tử và capacity là 16, tại địa chỉ 0x1200. Nếu ptr được gán = &data[0] = 0x1100 thì sau khi push_back thành 9 phần tử, giá trị của ptr sẽ bị invalid (0x1100 thay vì 0x1200)

và 1 lưu ý nữa là std::vector<bool> data thì ko xài bool* ptr = &data[0] được, vì std::vector<bool> nó lưu mỗi biến data[i] bool chỉ có 1 bit, nên trỏ con trỏ bool* tới 1 bit data[0] là ko đúng, vì kiểu bool có kích cỡ là 1 byte.


(Red Sand) #7

Mình cũng chưa biết mấy cái hành vi này của std::vector đâu ~.~, sure phải lưu ý nếu thêm function tăng kích thước. ptr thì hơi bắt buộc vì yêu cầu nhiều object dùng chung 1 data.


(‏) #8

nhiều object dùng chung 1 data thì xài hẳn pointer tới vector luôn std::vector<int>* pData, chậm hơn tí nhưng làm cho đúng đã tốc độ tính sau @_@


(Red Sand) #9

Mình cũng thấy xài ptr giống ôm bom vậy, cái giải thuật thì yêu cầu dùng chung 1 phần data chứ k dùng chung all. Mà trước đó k nghĩ ra dùng std::vector<int>* rồi thêm 1 biến int startSlot an toàn hơn nhiều @@.

Thắc mắc cuối vector *pData đổi memory location thì pData chắc cũng đổi vị trí nó trỏ tới, k biết pData của mấy copy-object có đổi luôn theo không?
Theo StackOverFlow có lẽ dùng std::list(mình chưa dùng bao giờ) thì an toàn hơn vector ở khoản memory location chăng?


(‏) #10

list an toàn nhưng ko truy cập [i] được, và ko tận dụng cache được nên có thể chậm hơn rất nhiều :V

pData thì dù mảng mà data giữ có đổi địa chỉ thì &(*pData)[0] vẫn đúng. Tốn 1 cái indirection (*pData) nữa nên chậm hơn xài thẳng ptr, nhưng ptr có thể bị invalidated và cũng chưa chắc chậm hơn bao nhiêu nên cứ xài pointer trỏ tới cả cái vector luôn, nếu thấy chậm ko chấp nhận được thì mới xài ptr trỏ thẳng int*

nếu data sống dai hơn mấy object xài nó, các object xài nó sử dụng ptr ko có giá trị null bao giờ, và 1 khi đã gán rồi ko gán qua data2 data3 gì nữa thì có thể xài thẳng reference: std::vector<int>& outsideData, gán ngay khi khởi tạo object: Object(std::vector<int>& data) : outsideData{data} {} khi đó lấy địa chỉ ko cần indirection &outsideData[0] hy vọng vậy :V


(rogp10) #11

Nó là DSLK (đôi) nên chỉ có đi tới, đi lui chứ không có [i] (chỉ số) được.


83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?