2009-04-18 62 views
20

Câu hỏi này có liên quan đến this one. Được cung cấp mã này:Xóa mảng char

char *p = new char[200]; 
delete[] p; 

điều gì sẽ xảy ra nếu bạn đặt p[100] = '\0' trước khi xóa p?

Tôi đã có một số mã mà tôi gặp phải lỗi gỡ lỗi khi cố xóa một mảng không được kết thúc bằng null, điều gì đó về xóa bộ nhớ heap không được gán. Dường như nó xóa bộ nhớ ra khỏi giới hạn của mảng.

Trả lời

38

Mã:

char *p = new char[200]; 
p[100] = '\0'; 
delete[] p; 

là hoàn toàn hợp lệ C++. xóa không biết hoặc quan tâm đến các chuỗi bị vô hiệu hóa, vì vậy lỗi của bạn phải có một số nguyên nhân khác.

+0

_ "xóa không biết hoặc quan tâm về không bị chấm dứt ..." _ điều này không đúng. nếu bạn có 'p [2]', sau đó bạn vô tình đặt 'p [2] = '\ 0'', việc xóa' p' sẽ đưa ra một lỗi liên quan đến bộ nhớ, rõ ràng vì việc xóa bộ nhớ tại p [2] là đã cố gắng. – user3140280

+0

Điều này đúng. Tôi đã có một tham nhũng heap cho một kịch bản chính xác tương tự. Tôi đã có một mảng kích thước 10. Tôi đặt mảng [10] = '\ 0' do nhầm lẫn và khi tôi xóa mảng [], tôi nhận được một lỗi tham nhũng đống. Sửa lỗi và nó đã biến mất. Đã học được điều gì đó mới mẻ. – Nazeeh

+10

@Nazeeh bạn có thể đã học được điều gì đó sai ở đây hoặc có thể không chính xác trích dẫn những gì bạn hiểu từ nó. Trong một mảng có kích thước 10, phần tử thứ 10 ở chỉ số thứ 9, không phải 10, nếu bạn đi và viết bất kỳ thứ gì vào chỉ mục thứ 10, bạn đã bị hỏng hóc, gọi xóa để làm hỏng ứng dụng của bạn là không liên quan, ứng dụng của bạn bị ràng buộc gặp sự cố dù sao, nó chỉ là vấn đề thời gian. Gọi xóa ngay sau khi sai lầm của bạn chỉ là bạn may mắn mà bạn đã nhìn thấy những sai lầm sớm hơn (và trong một trường hợp sử dụng đơn giản hơn) thay vì sau đó phải đi qua một chi tiết lộn xộn để phát hiện lỗi này. – user734028

3

Nó không quan trọng. delete [] nên được sử dụng để xóa mảng được phân bổ động bất chấp nội dung của nó.

8

Không có gì đặc biệt sẽ xảy ra. Bạn sẽ viết ở một số vị trí ở giữa bộ nhớ được cấp phát (100 byte ngoài phần bắt đầu, 99 byte trước khi kết thúc bộ nhớ được phân bổ).

Sau đó, bạn sẽ giải phóng bộ nhớ được cấp phát đó. Trình biên dịch sẽ xử lý nó chính xác như chúng ta mong đợi. Bộ nhớ được cấp phát bằng cách đó hoàn toàn không liên quan đến các chuỗi bị vô hiệu. Bạn có thể dán mọi thứ bạn muốn vào bộ nhớ đó. Đó là một số kho dữ liệu "thô", bạn thậm chí có thể tạo một số đối tượng C++ tùy ý vào bộ nhớ đó (vị trí mới).

Lỗi của bạn ở một nơi khác. Ví dụ, một số lỗi phổ biến là thế này, nơi các nhà xây dựng được gọi là một lần, nhưng destructor được gọi là hai lần, kích đúp xóa một cái gì đó:

struct A { P *p; A() { p = new P; } ~A() { delete p; } }; 
A getA() { return A(); } int main() { A a = getA(); } 

Bây giờ, những gì xảy ra là các nhà xây dựng mặc định được gọi là một lần, và đối tượng đã tạo được sao chép bằng không hoặc nhiều lần. Nhưng destructor được chạy cho mỗi bản sao được tạo ra. Vì vậy, bạn sẽ gọi destructor trên con trỏ nhiều hơn một lần, dẫn đến lỗi lạ như vậy. Cách chính xác để sửa lỗi rằng là sử dụng con trỏ thông minh, như shared_ptr. Như một bài tập, bạn cũng có thể làm điều đó mà không cần, bằng cách viết các nhà xây dựng sao chép thích hợp sao chép đối tượng qua và cấp phát bộ nhớ trong trình tạo bản sao, sao cho bản sao và đối tượng gốc tương ứng giữ các con trỏ riêng biệt.

1

Điều này sẽ hoạt động tốt, theo như tôi có thể biết. Bạn phân bổ một bộ nhớ, và hệ điều hành nên theo dõi nó, và có thể deallocate nó khi được hỏi. Nó không quan trọng ở tất cả các giá trị bạn đưa vào bộ đệm bạn đã phân bổ.

Gắn một NULL ở giữa một mảng ký tự chắc chắn sẽ can thiệp vào các hàm chuỗi C chẳng hạn như strcmp, strlen, v.v. nhưng đó là một vấn đề khác hoàn toàn.

6

Tôi nghĩ rằng bạn đang bối rối một mảng char cũ đồng bằng với một mảng char đại diện cho một chuỗi kiểu C. Toán tử xóa C++ không quan tâm đến mảng chuỗi kiểu C. Tất cả những gì nó từng thấy là một mảng các ký tự. Nó thực sự không khác với việc xóa một mảng int.

Sự hiện diện hoặc vắng mặt của trình kết thúc null chỉ có liên quan trong các hàm xử lý một kiểu chuỗi char*.

0

Như những người khác đã lưu ý, mã bạn đã đăng hoàn toàn hợp lệ và không gây ra bất kỳ sự cố nào.

Lỗi có thể xảy ra do thay đổi giá trị p ở đâu đó ở giữa.