Почему ZeroMemory и подобные вызовы существуют в Windows API, когда уже есть memset и связанные вызовы в стандартной библиотеке C? Какие из них я должен назвать? Я могу догадаться, что ответ «зависит». На что?Почему ZeroMemory и т. Д. Существуют, когда есть memset и т. Д. Уже?
ответ
В C и C++, ZeroMemory()
и memset()
являются точно то же самое.
/* In winnt.h */
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
/* In winbase.h */
#define ZeroMemory RtlZeroMemory
Зачем использовать ZeroMemory()
? To make it obvious. Но я предпочитаю memset()
в программах на C или C++.
Поскольку API Windows должен быть агностическим. Он обеспечивает достаточную функциональность для разработчиков, независимо от языка, который они используют. Конечно, в конечном итоге многие функции будут дублировать существующие функциональные возможности, предлагаемые языками.
Вы должны вызвать функции WinAPI (и макросы) непосредственно всякий раз, когда вам нужен определенный уровень контроля - сравнение fopen()
с CreateFile()
, например. В противном случае, предпочитайте специфические для языка конструкции над вызовами API. По крайней мере, вы получаете больше независимости от платформы.
Я не уверен, как вы напишете язык-агностический макрос. –
ZeroMemory представляется макросом для перекрестной номенклатуры MS-языка. Я проверил, как это возможно, системный трюк для очистки аппаратной памяти, который мог бы быть более эффективным. Вероятно, это просто синтаксический сахар для memset; игнорируй это. http://msdn.microsoft.com/en-us/library/aa366920(VS.85).aspx – msw
@Pete: если у вас есть ZeroMemory, определенный в C stdlib и, скажем, VBA, то ваш кодер использует то же имя для с той же целью и лучше заперта в Microsoft. Объятия и расширения, брат! http://en.wikipedia.org/wiki/Embrace,_extend_and_extinguish – msw
Согласно MSDN, ZeroMemory - это макрос. Вероятно, он существует как удобство (например, соглашение об именах) или для обратной совместимости.
Я бы пошел с обратной совместимостью вместе с этими функциями для обработки 32-битных чисел (я забыл имена) для деления и т. Д. –
ZeroMemory
и такие как часть самого API окон. memset
является частью стандартной библиотеки C.
Для типичного кода пользователя, я бы обычно использовал memset
(или эквивалент, предоставленный на вашем языке). Если вы пишете код ядра (например, драйвер устройства), используя что-то вроде ZeroMemory
, это более привлекательно. Так как ваш код выполняется в режиме ядра в любом случае, вы не берете на себя стоимость переключателя задачи для его использования. Поскольку он уже находится в коде Windows, вы не переносите дополнительный код в своем драйвере, чтобы дублировать то, что уже есть. В то же время вы несете стоимость вызова функции, а в случае или обнуления (особенно небольшого блока), встроенный код может быть значительно быстрее, а rep stosd
не занимает много кода (на самом деле, настройка и использование rep stosd
может занять меньше кода, вызываемого вызовом функции).
В новых компиляторах Visual Studio 'memset()' является неотъемлемой функцией. Это означает, что он реализован самим компилятором, и во многих случаях вызов функции отсутствует. Компилятор строит его с помощью специально созданного ассемблерного кода для наилучшего использования на основе целевой архитектуры, длины и выравнивания памяти для перезаписываемых данных. – BJovke
@BJovke: это не особенно недавняя инновация. Он возвращается, по крайней мере, к MS C 6.0 (примечание: MS C, а не VC++), который (для памяти, так что это может быть немного неправильно) был выпущен примерно в 1989 или 1990 годах. Я предполагаю, что я не сказал этого непосредственно в ответе, но это было связано с накладными расходами на вызов функции (т. Е. Использование «ZeroMemory» связано с вызовом функции, но использование «memset» часто не будет) , –
Потому что, ZeroMemory не требуют линии комментария
Я думаю, что один момент состоит в том, что функции распределения памяти должны выглядеть одинаково во всех проектах Win32, независимо от языка программирования. Действительно, как указывалось ранее, в C, ZeroMemory - фактически memset, функция C. В Delphi,
procedure ZeroMemory(Destination: Pointer; Length: DWORD);
begin
FillChar(Destination^, Length, 0);
end;
где FillChar - это функция Delphi. И так далее:
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;
...
На самом деле из темы, но как разработчик Delphi, я стараюсь использовать MoveMemory (или CopyMemory - они идентичны), когда у меня есть указатели, и Move, когда у меня есть переменные, поэтому мне не нужно использовать «@» или « ^». –
Фактическая причина заключается в том, что на другой платформе может быть реализован более эффективно, чем memset
. Не забывайте, что Windows NT была разработана как портативная операционная система, она фактически работала на Alpha, MIPS и Power PC. Итак, если платформа fooPC вышла и имеет некоторый способ сборки до ультрабыстрого набора памяти до нуля, ее можно реализовать без изменения API высокого уровня. Это больше не относится к Windows, поскольку теперь оно поддерживает только платформы x86 и amd64, однако это верно для Windows CE.
На самом деле, что вам хочу использовать SecureZeroMemory()
.
Оптимизированный компилятор может удалить вызовы memset()
, а SecureZeroMemory()
предназначен для предотвращения этого.
Раньше я думал, что звонки не нужны, пока я не наткнулся на этот факт.
Дополнительная ссылка: https://msdn.microsoft.com/en-us/library/ms972826.aspx – Pang
Это большая проблема, как я заметил в своем ответе: оптимизация компиляторов может удалить вызовы 'memset()', поэтому вы действительно хотите использовать что-то, что не будет оптимизировано. –
@ richard.albury в этом случае вы должны использовать SecureZeroMemory, так как ZeroMemory можно было бы оптимизировать. – ya23