Một số thời gian trước đây tôi đọc một bài báo giải thích một số cạm bẫy của tra cứu phụ thuộc đối số, nhưng tôi không thể tìm thấy nó nữa. Đó là về việc đạt được quyền truy cập vào những thứ mà bạn không nên có quyền truy cập vào hoặc một cái gì đó như thế. Vì vậy, tôi nghĩ rằng tôi muốn hỏi ở đây: những cạm bẫy của ADL là gì?Cạm bẫy của ADL là gì?
Trả lời
Có vấn đề lớn với tra cứu phụ thuộc vào đối số. Hãy xem xét, ví dụ: tiện ích sau:
#include <iostream>
namespace utility
{
template <typename T>
void print(T x)
{
std::cout << x << std::endl;
}
template <typename T>
void print_n(T x, unsigned n)
{
for (unsigned i = 0; i < n; ++i)
print(x);
}
}
Đơn giản, phải không? Chúng ta có thể gọi print_n()
và vượt qua bất kỳ đối tượng nào và nó sẽ gọi print
để in đối tượng n
lần.
Thực tế, hóa ra là nếu chúng ta chỉ xem mã này, chúng tôi có hoàn toàn không có ý tưởng chức năng nào sẽ được gọi bởi print_n
. Nó có thể là mẫu chức năng print
được đưa ra ở đây, nhưng nó có thể không được. Tại sao? Tra cứu phụ thuộc vào đối số.
Ví dụ: giả sử bạn đã viết một lớp để đại diện cho một con kỳ lân. Vì lý do nào đó, bạn cũng đã xác định một hàm có tên là print
(thật trùng hợp!) Mà chỉ khiến chương trình bị lỗi bằng cách ghi vào con trỏ null (ai biết tại sao bạn làm điều này; điều đó không quan trọng):
namespace my_stuff
{
struct unicorn { /* unicorn stuff goes here */ };
std::ostream& operator<<(std::ostream& os, unicorn x) { return os; }
// Don't ever call this! It just crashes! I don't know why I wrote it!
void print(unicorn) { *(int*)0 = 42; }
}
Tiếp theo, bạn viết một chương trình nhỏ mà tạo ra một con kỳ lân và in nó gấp bốn lần:
int main()
{
my_stuff::unicorn x;
utility::print_n(x, 4);
}
bạn biên dịch chương trình này, chạy nó, và ... nó bị treo. "Cái gì ?! Không có cách nào," bạn nói: "Tôi chỉ gọi là print_n
, gọi hàm print
để in lân bốn lần!" Có, đó là sự thật, nhưng nó đã không được gọi là chức năng print
bạn mong đợi nó để gọi. Nó được gọi là my_stuff::print
.
Tại sao chọn my_stuff::print
? Trong quá trình tra cứu tên, trình biên dịch thấy rằng đối số cho cuộc gọi đến print
là loại unicorn
, là loại lớp được khai báo trong không gian tên my_stuff
.
Do tra cứu phụ thuộc vào đối số, trình biên dịch bao gồm không gian tên này trong tìm kiếm của nó cho các hàm ứng viên có tên là print
. Nó tìm thấy my_stuff::print
, sau đó được chọn là ứng viên khả thi tốt nhất trong quá trình phân giải quá tải: không cần chuyển đổi để gọi một trong hai chức năng print
và chức năng nontemplate được ưu tiên cho mẫu chức năng, do đó hàm nontemplate my_stuff::print
là kết quả phù hợp nhất.
(Nếu bạn không tin điều này, bạn có thể biên dịch mã trong câu hỏi này như-là và xem ADL trong hành động.)
Vâng, tra cứu luận phụ thuộc là một tính năng quan trọng của C++. Về bản chất, nó được yêu cầu để đạt được hành vi mong muốn của một số tính năng ngôn ngữ như các toán tử quá tải (xem xét thư viện suối). Điều đó nói rằng, nó cũng rất, rất thiếu sót và có thể dẫn đến những vấn đề thực sự xấu xí. Đã có một số đề xuất để sửa chữa tra cứu phụ thuộc vào đối số, nhưng không có đề xuất nào được chấp nhận bởi ủy ban tiêu chuẩn C++.
- 1. Cạm bẫy của việc sử dụng sql_variant là gì?
- 2. auto_ptr Bẫy và Cạm bẫy
- 3. Cạm bẫy của các ứng dụng Android
- 4. Những cạm bẫy và gotchas của trộn Objective-C và C là gì?
- 5. Những cạm bẫy của kết nối được nhúng vào Derby qua mạng là gì?
- 6. Những cạm bẫy phổ biến khi sử dụng eval của Perl là gì?
- 7. Những cạm bẫy phổ biến của đồng bộ hóa dựa trên dấu thời gian là gì?
- 8. Cạm bẫy của thử nghiệm sau khi phát triển là gì?
- 9. Angular JS: những vấn đề/cạm bẫy của việc sử dụng Angular là gì?
- 10. Những cạm bẫy khi thiết lập enable_nestloop là OFF
- 11. Cạm bẫy hiệu suất hibernate thông thường
- 12. Cạm bẫy miền-thiết kế (DDD)
- 13. Mẫu thiết kế Singleton: Cạm bẫy
- 14. cạm bẫy svn -> git migration
- 15. Các cạm bẫy hiệu suất của Apache Velocity?
- 16. Sử dụng cookie cho trạng thái phiên web - những cạm bẫy là gì?
- 17. Một số cạm bẫy Java phổ biến/gotchas cho lập trình C++ là gì?
- 18. Những cạm bẫy có thể xảy ra khi chuyển Psyco sang 64-bit là gì?
- 19. Các vấn đề phát triển chung, cạm bẫy và đề xuất là gì?
- 20. Những cạm bẫy khi sử dụng FlexibleContexts và FlexibleInstances là gì?
- 21. Các luồng hoạt động như thế nào trong Python, và những cạm bẫy cụ thể của Python là gì?
- 22. Cạm bẫy JavaScript không xác định rõ ràng?
- 23. SharePoint 2007 - RunWithElevatedPrivileges - Cạm bẫy khi sử dụng này
- 24. Những cạm bẫy của việc thực thi jQuery mà không có $ (tài liệu) .ready() ;?
- 25. Những cạm bẫy cố gắng sử dụng PLINQ trên các máy phát điện chạy dài?
- 26. Tiềm năng cạm bẫy với các nhà thầu tĩnh trong C#
- 27. Thanh toán định kỳ với Rails và ActiveMerchant: Thực tiễn tốt nhất, cạm bẫy, gotchas?
- 28. Những cạm bẫy tiềm năng trong việc sử dụng hàng đợi JMS?
- 29. Bất kỳ cạm bẫy nào khi sử dụng các công thức được lập trình sẵn?
- 30. Cạm bẫy/công việc triển khai ClickOnce/smart-client trong .NET
Tôi có lẽ nên lưu ý rằng ví dụ này được lấy cảm hứng từ một bài thuyết trình về chủ đề mà Bartosz Milewski đã đưa ra; Tôi không có các slide từ bài thuyết trình đó, và nó không hoàn toàn giống nhau, nhưng nó rất gần. –
Đây có phải là một lỗ hổng của ADL hoặc pitfall của việc không sử dụng ADL một cách cẩn thận? – Chubsdad
@Chubsdad: Đó là một lỗ hổng lớn của ADL. Vấn đề là bạn có thể viết hai thư viện hoàn toàn độc lập và vô tình chạy vào vấn đề này mà không có bất kỳ ý tưởng rằng bạn sẽ có vấn đề. Không có số lượng "cẩn thận" hoàn toàn có thể bảo vệ bạn khỏi điều này. –