2012-10-31 25 views
14

Tôi có hai khối mã về new[]delete[]:Sau khi p = chuỗi mới [0] và p = new int [0], tại sao phiên bản chuỗi bị treo khi xóa [] p?

1)

#include <string> 

int main() 
{ 
    std::string *p = new std::string[0]; 
    delete[] p; 

    return 0; 
} 

2) Trong trường hợp này, tôi chỉ đơn thuần là thay đổi std::string để int

int main() 
{ 
    int *p = new int[0]; 

    delete[] p; 

    return 0; 
} 

Câu hỏi của tôi là:

Tại sao chương trình đầu tiên gặp sự cố với thông báo sau (trong môi trường linux):

Segmentation fault (core dumped) 

Nhưng chương trình thứ hai hoạt động tốt mà không có bất kỳ lỗi nào?

EDIT

biên dịch: g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

tôi chỉ sử dụng g++ mà không cần bất kỳ lý lẽ để biên dịch nó.

Nếu đó là lỗi trình biên dịch, chúng có bị lỗi hay không theo tiêu chuẩn?

+2

Trông giống như một trình biên dịch lỗi – Andrey

+1

Nó không sụp đổ ở đây. Trình biên dịch bạn đang sử dụng (với phiên bản chính xác) và làm thế nào bạn biên dịch nó? – amaurea

+1

Tai nạn với g ++ (4.7 & 4.8), không bị sập. Tôi đoán đó là một lỗi g ++. – kennytm

Trả lời

13

Đây phải là lỗi gcc. Đó là toàn bộ biểu thức new[] bị bỏ qua và p trở thành uninitialized, và sau đó chúng tôi delete[] một con trỏ uninitialized mà tai nạn. Nếu chúng ta biên dịch chương trình với -Wall nó sẽ cảnh báo bạn rằng

cảnh báo: ‘p’ được sử dụng chưa được khởi tạo trong hàm này

đó rõ ràng là sai. Biểu thức new X[0] được xác định rõ trong cả C++ 03 và C++ 11 (§5.3.4/7), và điều này hoạt động chính xác trong tiếng kêu, do đó, kết luận logic duy nhất là đó là lỗi gcc.


Lỗi loại bỏ-of-new[] chỉ tồn tại khi loại được xây dựng có bất kỳ nhà xây dựng không tầm thường nào. Và segfault xảy ra loại có một destructor, bởi vì delete[] sau đó sẽ cần phải dereference rằng uninitialized con trỏ. Do đó, lỗi này bị treo cho std::string nhưng không phải là int, bởi vì int là tầm thường và std::string thì không.


này có thể được giải quyết bằng cách sử dụng một biến trung gian, chẳng hạn rằng biểu thức không thể được đánh giá để 0 trực tiếp:

size_t length = 0; 
std::string* p = new std::string[length]; 
// ... 
delete[] p; 
+0

Tôi ngạc nhiên về công việc hack ... Trên liveworkspace tôi có 3 hành vi: mã OP ban đầu (cảnh báo + lỗi), công việc này (không cảnh báo, không có sự cố), sử dụng 'size_t const length = 0;' (cảnh báo, không có sự cố). Tôi * yêu * gcc ... –