2010-06-14 46 views

Trả lời

30

Trong C và C++, ZeroMemory()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++.

+2

Đó 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. –

+3

@ 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

5

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.

+3

Tôi không chắc chắn cách bạn viết macro vĩ mô về ngôn ngữ. –

+0

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

+1

@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

1

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.

+0

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. –

8

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).

+0

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

+0

@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) . –

3

Bởi vì, ZeroMemory không yêu cầu dòng comment

3

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; 

... 
+0

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 "^". –

11

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.

1

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()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.

+0

Tham khảo bổ sung: https://msdn.microsoft.com/en-us/library/ms972826.aspx – Pang

Các vấn đề liên quan