Tại sao ZeroMemory, và các cuộc gọi tương tự tồn tại trong Windows API khi có memset và các cuộc gọi liên quan trong thư viện chuẩn C? Tôi nên gọi cho ai? Tôi có thể đoán câu trả lời là "phụ thuộc". Về những gì?Tại sao ZeroMemory, vv tồn tại khi có memset, vv?
Trả lời
Trong C và C++, ZeroMemory()
và memset()
là những điều chính xác cùng.
/* In winnt.h */
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
/* In winbase.h */
#define ZeroMemory RtlZeroMemory
Tại sao sử dụng ZeroMemory()
thì? To make it obvious. Nhưng tôi thích memset()
trong các chương trình C hoặc C++.
Do API Windows nên không có khả năng ngôn ngữ. Nó cung cấp đầy đủ chức năng cho các nhà phát triển, bất kể ngôn ngữ họ sử dụng. Tất nhiên, cuối cùng nhiều chức năng sẽ nhân đôi chức năng hiện có được cung cấp bởi các ngôn ngữ.
Bạn nên gọi hàm winapi (và macro) trực tiếp bất cứ khi nào bạn cần một mức kiểm soát nhất định - so sánh fopen()
với CreateFile()
chẳng hạn. Nếu không, hãy chọn cấu trúc dành riêng cho ngôn ngữ qua các cuộc gọi API. Ít nhất, bạn có được nền tảng độc lập hơn.
Tôi không chắc chắn cách bạn viết macro vĩ mô về ngôn ngữ. –
ZeroMemory dường như là một macro cho danh mục MS qua ngôn ngữ. Tôi đã kiểm tra vì nó có thể là một mẹo hệ thống để xóa bộ nhớ phần cứng có thể hiệu quả hơn. Nó có lẽ chỉ là đường cú pháp để ghi nhớ; Phớt lờ nó đi. http://msdn.microsoft.com/en-us/library/aa366920(VS.85).aspx – msw
@Pete: nếu bạn có ZeroMemory được định nghĩa trong stdlib C và - nói VBA - thì trình coder của bạn sử dụng cùng một tên cho cùng một mục đích và tốt hơn là khóa vào Microsoft. Embrace và mở rộng, anh trai! http://en.wikipedia.org/wiki/Embrace,_extend_and_extinguish – msw
Theo MSDN, ZeroMemory là macro. Nó có thể tồn tại như một sự thuận tiện (ví dụ, quy ước đặt tên) hoặc cho khả năng tương thích ngược.
Tôi muốn đi với khả năng tương thích ngược, cùng với các chức năng để xử lý các số 32 bit (tôi quên tên) để phân chia vv. –
ZeroMemory
và đó là một phần của chính API cửa sổ. memset
là một phần của thư viện chuẩn C.
Đối với mã người dùng điển hình, tôi thường sử dụng memset
(hoặc tương đương được cung cấp bởi ngôn ngữ bạn chọn). Nếu bạn đang viết mã hạt nhân (ví dụ: trình điều khiển thiết bị), hãy sử dụng thứ gì đó như ZeroMemory
sẽ hấp dẫn hơn. Vì mã của bạn thực thi trong chế độ hạt nhân, bạn không phải chịu chi phí của một công việc chuyển đổi để sử dụng nó. Kể từ khi nó đã có trong mã Windows, bạn không mang theo mã thêm trong trình điều khiển của bạn để nhân đôi những gì đã có. Đồng thời, bạn phải chịu chi phí của một cuộc gọi hàm, và trong trường hợp hoặc zeroing (đặc biệt là một khối nhỏ) bộ nhớ, mã nội tuyến có thể nhanh hơn đáng kể, và một rep stosd
không mất nhiều mã (trên thực tế, thiết lập và sử dụng rep stosd
có thể mất ít mã hơn mà một cuộc gọi chức năng).
Trong các trình biên dịch Visual Studio mới hơn 'memset()' là một hàm bên trong. Điều đó có nghĩa rằng nó được thực hiện bởi trình biên dịch chính nó và trong nhiều trường hợp không có cuộc gọi chức năng. Trình biên dịch inline nó với mã lắp ráp đặc biệt crafted để thực hiện tốt nhất dựa trên kiến trúc mục tiêu, chiều dài và liên kết bộ nhớ dữ liệu được ghi đè. – BJovke
@BJovke: đó không phải là một sự đổi mới đặc biệt gần đây. Nó quay trở lại ít nhất là MS C 6.0 (lưu ý: MS C, không phải VC++), mà (dành cho bộ nhớ, do đó, nó có thể là một chút sai) đã được phát hành khoảng năm 1989 hoặc '90. Tôi đoán tôi đã không nói trực tiếp trong câu trả lời, nhưng đó là điểm đề cập đến chi phí của một cuộc gọi hàm (tức là, sử dụng 'ZeroMemory' sẽ liên quan đến một cuộc gọi hàm, nhưng sử dụng' memset' thường không được) . –
Bởi vì, ZeroMemory không yêu cầu dòng comment
Tôi nghĩ một điểm là các chức năng cấp phát bộ nhớ sẽ giống nhau trong tất cả các dự án Win32, độc lập với ngôn ngữ lập trình. Thật vậy, như đã được chỉ ra trước đó, trong C, ZeroMemory thực sự là memset, hàm C. Tại Delphi,
procedure ZeroMemory(Destination: Pointer; Length: DWORD);
begin
FillChar(Destination^, Length, 0);
end;
trong đó FillChar là hàm Delphi. Và như vậy:
procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
begin
Move(Source^, Destination^, Length);
end;
procedure FillMemory(Destination: Pointer; Length: DWORD; Fill: Byte);
begin
FillChar(Destination^, Length, Fill);
end;
...
Thực sự ngoài chủ đề, nhưng với tư cách là nhà phát triển Delphi, tôi có xu hướng sử dụng MoveMemory (hoặc CopyMemory - chúng giống nhau) khi tôi có con trỏ và Di chuyển khi tôi có biến, vì vậy tôi không phải sử dụng "@" hoặc "^". –
Lý do thực tế là trên một nền tảng khác có thể được triển khai theo cách hiệu quả hơn memset
. Đừng quên rằng Windows NT được thiết kế như một hệ điều hành di động cao, nó thực sự chạy trên Alpha, MIPS và Power PC. Vì vậy, nếu nền tảng fooPC xuất hiện và có một số cách lắp ráp để bộ nhớ cực nhanh được đặt thành 0, nó có thể được triển khai mà không thay đổi API cấp cao. Điều này không còn đúng đối với Windows, vì bây giờ nó chỉ hỗ trợ các nền tảng x86 và amd64, tuy nhiên nó vẫn đúng đối với Windows CE.
Thực tế, những gì bạn muốn để sử dụng là SecureZeroMemory()
.
Trình biên dịch tối ưu hóa có thể xóa cuộc gọi tới memset()
và SecureZeroMemory()
được thiết kế để ngăn chặn điều này.
Tôi từng nghĩ rằng các cuộc gọi ZeroMemory()
là không cần thiết cho đến khi tôi bắt gặp thực tế này.
Tham khảo bổ sung: https://msdn.microsoft.com/en-us/library/ms972826.aspx – Pang
- 1. GeneratedMethodAccessor1,2, vv và tại sao chúng không tìm thấy?
- 2. Tại sao mDNS (Bonjour, Avahi, vv) sử dụng UDP?
- 3. loại tại Scala, Long, Int vv
- 4. Tại sao nên sử dụng LISP ngay hôm nay, khi có Scala, Erlang, Haskell vv
- 5. Tại sao C# xử lý 0 là int và không phải là ngắn/thập phân vv?
- 6. Lớp học "if/except" vv
- 7. Tại sao Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Equals() tồn tại?
- 8. Tại sao `ScalaObject` tồn tại?
- 9. Tại sao Console.Out.WriteLine tồn tại?
- 10. Tại sao putchar, toupper, tolower, vv lấy một int thay vì một char?
- 11. Tại sao bool.TrueString và bool.FalseString tồn tại?
- 12. các nút không có href, onclick vv
- 13. blogengine không có php hoặc asp.net vv
- 14. Tại sao các ID tồn tại?
- 15. PDO :: PARAM_FLOAT không tồn tại, tại sao?
- 16. Đúc Lớp tôi để Int64, đôi vv
- 17. Destructors các loại BUILTIN (int, char vv ..)
- 18. glEnableClientState với OpenGL hiện đại (glVertexAttribPointer vv)
- 19. Thoát git bash sau khi reflog, hoặc cam kết, vv
- 20. Tại sao các chức năng như thoát, unescape, vv, không phải là các phương thức trên đối tượng String?
- 21. Tại sao CreateFileMapping trả về "tệp đã tồn tại"?
- 22. kilobyte Chuyển đổi, megabyte vv để byte trong R
- 23. Tại sao từ khóa không đồng bộ tồn tại
- 24. Tại sao localStorage không tồn tại trong Chrome?
- 25. bắt đầu mã javascript với $ (function, vv
- 26. Django xác nhận ImageField kích thước vv
- 27. Tại sao Firebug đánh các điểm ngắt không tồn tại?
- 28. Tại sao system.float không tồn tại trong .net?
- 29. Tại sao SQLite nói rằng instr không tồn tại?
- 30. Tại sao phương thức tĩnh Tạo tồn tại?
Đó là một vấn đề lớn hơn, như tôi đã lưu ý trong câu trả lời của tôi: tối ưu hóa các trình biên dịch có thể loại bỏ các cuộc gọi đến 'memset()', vì vậy bạn thực sự muốn sử dụng thứ gì đó sẽ không được tối ưu hóa. –
@ richard.albury trong trường hợp đó bạn nên sử dụng SecureZeroMemory, vì ZeroMemory có thể được tối ưu hóa. – ya23