2013-06-24 26 views
5

tôi có thể sử dụng smth như đoạn mã sau:điều hành xóa và đúc

int main() 
{ 
    int* foo = new int; 
    double* bar = reinterpret_cast<double*>(foo); 
    delete bar; 
} 

Có UB?

Tôi nghĩ rằng chúng ta cần phải gọi toán tử xóa chỉ cho con trỏ được trả về bởi toán tử mới, nhưng điều gì về việc đúc trong trường hợp này?

Tôi nghĩ rằng đó là UB vì reinterpret_cast không đưa ra bất kỳ đảm bảo nào về con trỏ kết quả. Tôi có đúng không?

Ai đó có thể đăng câu đúng từ tiêu chuẩn không?

+2

Lưu ý rằng UB ở đây nằm trong biểu thức xóa, chứ không phải toán tử xóa. – PlasmaHH

+0

Ok, vậy UB ở đây là gì? Bạn có thể đăng báo giá từ tiêu chuẩn không? – FrozenHeart

Trả lời

6

§5.3.5/2 "Trong phương án đầu tiên (xóa đối tượng), giá trị của các toán hạng của xóa có thể là một giá trị con trỏ null, một con trỏ đến một đối tượng không cho mảng được tạo ra bởi một mới- trước biểu thức, hoặc một con trỏ tới một đối tượng con (1.8) đại diện cho một lớp cơ sở của một đối tượng (Điều 10). Nếu không, hành vi này là không xác định. " Vì bar trỏ đến một double, nó không trỏ đến một đối tượng được tạo bởi biểu thức mới trước đó (đã tạo ra một int).

+0

Loại tĩnh và động trong trường hợp này là gì? – FrozenHeart

+0

'int' và' double', tương ứng. Nhưng ngay cả khi các từ ngữ của tiêu chuẩn là quá phức tạp để hiểu, chỉ cần xem xét rằng bạn đang gọi các nhà xây dựng sai với những gì bạn làm. Điều này nên rõ ràng ngay cả khi không có báo giá ở trên. Cả hai destructors là tầm thường như nó xảy ra, do đó, nó "sẽ làm việc", nhưng nó vẫn còn rất rõ ràng UB. – Damon

+0

@NikitaTrophimov, Thêm tại đây: http://stackoverflow.com/questions/1347691/static-vs-dynamic-type-checking-in-c – chris

0

Ở đây bạn là:

5.3.5 điểm 3: Trong phương án đầu tiên (xóa đối tượng), nếu loại tĩnh của đối tượng bị xóa là khác nhau từ loại năng động của nó, loại tĩnh sẽ là lớp cơ sở của loại động của đối tượng cần xóa và loại tĩnh sẽ có trình phá hủy ảo hoặc hành vi không xác định.

Đối với câu hỏi về những gì là tĩnh và loại động:

1.3.7 loại động (glvalue)
loại đối tượng có nguồn gốc nhất (1.8) mà glvalue biểu thị bằng glvalue biểu thức đề cập đến [Ví dụ: nếu một con trỏ (8.3.1) p có kiểu tĩnh là “con trỏ đến lớp B” trỏ đến một đối tượng thuộc lớp D, bắt nguồn từ B (Điều 10), kiểu động của biểu thức * p là “D.” Tài liệu tham khảo (8.3.2) được xử lý tương tự. -end dụ]

1.3.23 kiểu tĩnh
loại một biểu thức (3.9) kết quả từ phân tích của chương trình mà không xem xét ngữ nghĩa thực [Lưu ý: Các loại tĩnh của một biểu thức chỉ phụ thuộc vào hình thức của chương trình trong đó biểu thức xuất hiện và không thay đổi trong khi chương trình đang thực thi. -end note]

+0

Ngoài ra. (Đó thực sự là đoạn mà tôi đang tìm kiếm khi tôi tìm thấy câu trả lời của mình.) –

+0

Loại tĩnh và động trong trường hợp này là gì? – FrozenHeart

+1

Kiểu tĩnh là loại con trỏ ('double'). Kiểu động là kiểu con trỏ ('int'). –

2

Từ 5.3.5-3:

Trong phương án đầu tiên (xóa đối tượng), nếu loại tĩnh của đối tượng bị xóa là khác biệt so với loại động của nó, loại tĩnh phải là một lớp cơ sở của loại động của đối tượng được bị xóa và loại tĩnh sẽ có một destructor ảo hoặc hành vi là không xác định.

Bỏ qua các vấn đề có thể xảy ra khi sử dụng reinterpret_cast tại đây, đây là UB vì các loại không khớp. Hãy tưởng tượng một số loại nontrivial, sau đó bạn có thể dễ dàng nhìn thấy điều này như là "sai" dtor sẽ được gọi.

Ngoài ra, sử dụng kết quả của reinterpret_cast cho bất kỳ mục đích nào khác ngoài việc truyền lại, phần lớn không được chỉ định theo tiêu chuẩn.

+0

Loại tĩnh và động trong trường hợp này là gì? – FrozenHeart

+1

@NikitaTrophimov: Kiểu động của đối tượng là int, vì đối tượng đã được tạo dưới dạng int và tĩnh của biểu thức là gấp đôi, khi bạn xử lý điều đó dưới dạng gấp đôi tại điểm đó. – PlasmaHH

+0

Bạn có ý kiến ​​khác với những người từ các câu trả lời khác :) – FrozenHeart