обнуление память

Я просто переместил иконку удаления css на элемент :after, и он отлично работает IE11 . Я надеюсь, что это поможет вам. Благодарю

.my-link {
      color: inherit;
      text-decoration: none;
    }

    .my-link:after {
      background-image: url(https://upload.wikimedia.org/wikipedia/commons/1/16/Deletion_icon.svg);
      background-repeat: no-repeat;
      background-size: contain;
      background-position: right;
      padding-right: 30px;
      content: '';
    }

.my-link:hover {
  color: red;
}

.my-link:hover::after {
  background-image: url(https://cdn1.iconfinder.com/data/icons/warnings-and-dangers/400/Warning-02-512.png);
}
<a class="my-link">My link</a>

24
задан Bo Persson 24 August 2011 в 18:45
поделиться

12 ответов

Худшее, что может случиться? В итоге (невольно) вы получаете строку, которая не заканчивается NULL, или целое число, которое наследует то, что произошло справа от него после печати в часть буфера. Тем не менее, неопределенные строки могут происходить и другими способами, даже если вы инициализировали буфер.

Редактировать (из комментариев) Конец света также маловероятен, в зависимости от того, что вы делаете.

Любой из них нежелателен. Однако, если полностью не избегать динамически распределенной памяти, большинство статически распределенных буферов обычно довольно малы, что делает memset() относительно дешевым. На самом деле, гораздо дешевле, чем большинство звонков в calloc() для динамических блоков, которые, как правило, превышают ~ 2k.

c99 содержит язык, касающийся значений инициализации по умолчанию, однако я не могу согласиться с этим gcc -std=c99, используя любой тип хранилища.

Тем не менее, с большим количеством старых компиляторов (и компиляторов, которые не совсем c99) все еще используются, я предпочитаю просто использовать memset()

12
ответ дан Tim Post 28 November 2019 в 22:56
поделиться

Когда вы определите char buffer[1024] без инициализации, вы получите неопределенные данные. Например, Visual C ++ в режиме отладки будет инициализироваться с 0xcd. В режиме Release он просто выделяет память и не заботится о том, что происходит в этом блоке от предыдущего использования.

Кроме того, ваши примеры демонстрируют инициализацию времени выполнения и времени компиляции. Если ваше char buffer[1024] = { 0 } является глобальным или статическим объявлением, оно будет храниться в сегменте данных двоичного файла с его инициализированными данными, таким образом увеличивая ваш двоичный размер примерно на 1024 байта (в данном случае). Если определение находится в функции, оно хранится в стеке и выделяется во время выполнения, а не сохраняется в двоичном файле. Если вы предоставляете инициализатор в этом случае, инициализатор сохраняется в двоичном файле, и эквивалент memcpy() делается для инициализации buffer во время выполнения.

Надеюсь, это поможет вам решить, какой метод лучше всего подходит для вас.

10
ответ дан spoulson 28 November 2019 в 22:56
поделиться

Одна из вещей, которая может произойти, если вы не инициализируете, - это риск утечки конфиденциальной информации.

Неинициализированная память может иметь что-то чувствительное от предыдущего использования этой памяти. Может быть, пароль или криптографический ключ или часть личного электронного письма. Ваш код может позже передать этот буфер или структуру куда-нибудь, или записать его на диск, и если вы только частично наполнили его, остальная часть все еще содержит это предыдущее содержимое. Некоторые защищенные системы требуют обнуления буферов , когда адресное пространство может содержать конфиденциальную информацию.

3
ответ дан progrmr 28 November 2019 в 22:56
поделиться

В данном конкретном случае особой разницы нет. Я предпочитаю = {0} , а не memset , потому что memset более подвержен ошибкам:

  • Он дает возможность получить неправильные границы.
  • Это дает возможность смешивать аргументы memset (например, memset (buf, sizeof buf, 0) вместо memset (buf, 0, sizeof buf) ) .

В общем случае = {0} лучше подходит для инициализации struct s. Он фактически инициализирует все члены, как если бы вы написали = 0 для инициализации каждого из них. Это означает, что элементы-указатели гарантированно инициализируются нулевым указателем (, который может не иметь значения all-bit-zero , а all-bit-zero - это то, что вы получите если вы использовали memset ).

С другой стороны, = {0} может оставить биты заполнения в struct как мусор, поэтому он может не будет подходящим, если вы планируете использовать memcmp для сравнения их позже.

8
ответ дан 28 November 2019 в 22:56
поделиться

Я предпочитаю использовать memset для очистки части памяти, особенно при работе со строками. Я хочу знать без сомнения, что после моей строки будет нулевой разделитель. Да, я знаю, что вы можете добавить \ 0 в конец каждой строки, и некоторые функции делают это за вас, но я не хочу сомневаться, что это произошло.

При использовании вашего буфера функция может выйти из строя, и буфер останется неизменным. Вы бы предпочли буфер неизвестного мусора или ничего?

3
ответ дан 28 November 2019 в 22:56
поделиться

Это сообщение было сильно отредактировано, чтобы сделать его правильным. Большое спасибо Тайлеру МакХенери за то, что он указал на то, что я пропустил.

char buffer[1024] = {0};

Устанавливает первый символ в буфере равным нулю, а затем компилятор также расширяет все неинициализированные символы до 0. В таком случае кажется, что различия между двумя методами сводятся к тому, генерирует ли компилятор более оптимизированный код для инициализации массива или memset оптимизируется быстрее, чем сгенерированный скомпилированный код.

Ранее я говорил:

char buffer [1024] = {0};

Устанавливает первый символ в буфере обнулить. Эта техника обычно используется для строк с завершающим нулем, как все данные после первого нуля игнорируется последующими (не глючит) функции, которые обрабатывают завершение нулем струны.

Что не совсем так. Приносим извинения за недопонимание и еще раз благодарим за исправления.

2
ответ дан 28 November 2019 в 22:56
поделиться

Зависит от того, как вы его заполняете: если вы планируете писать в него, прежде чем даже потенциально что-нибудь читать, тогда зачем беспокоиться? Это также зависит от того, для чего вы собираетесь использовать буфер: если он будет обрабатываться как строка, вам просто нужно установить первый байт на \ 0 :

char buffer[1024];
buffer[0] = '\0';

Однако, если вы если вы используете его как поток байтов, тогда содержимое всего массива, вероятно, будет релевантным, поэтому memset использует все это целиком или устанавливает для него значение {0} , как в ваш пример - умный ход.

2
ответ дан 28 November 2019 в 22:56
поделиться

Я также использую memset(buffer, 0, sizeof(buffer));

Риск неиспользования заключается в том, что нет гарантии, что используемый вами буфер полностью пуст, в нем может быть мусор, что может привести к непредсказуемому поведению.

Всегда выставляйте значение 0 после malloc - это очень хорошая практика.

1
ответ дан 28 November 2019 в 22:56
поделиться

Худшее, что может случиться, если этого не сделать, - это то, что вы пишете некоторые данные посимвольно, а затем интерпретируете их как строку (и вы не писали нулевой терминатор). Или вы в конечном итоге не можете понять, что какой-то его раздел был неинициализирован, и читаете его, как если бы это были достоверные данные. В основном: всякая гадость.

Memset должен быть в порядке (при условии, что вы исправите опечатку в размере :-)). Я предпочитаю это вашему первому примеру, потому что думаю, что он более понятен.

Для динамически выделяемой памяти я использую calloc, а не malloc и memset.

3
ответ дан 28 November 2019 в 22:56
поделиться

Да, метод calloc (), определенный в stdlib.h, выделяет память, инициализированную нулями.

1
ответ дан 28 November 2019 в 22:56
поделиться

Я не знаком с техникой:

char buffer[1024] = {0};

. Но если предположить, что он делает то, что я думаю, между этими двумя методами есть (потенциальная) разница.

Первый выполняется во время КОМПИЛЯЦИИ, и буфер будет частью статического образа исполняемого файла и, таким образом, будет нулем при загрузке.

Последнее будет сделано во ВРЕМЯ РАБОТЫ.

Первый может вызвать некоторое поведение во время загрузки. Если у вас есть только:

char buffer[1024];

современные загрузчики вполне могут «виртуально» загрузить это ... то есть, это не займет никакого реального места в файле, это будет просто инструкцией загрузчику вырезать блокировать при загрузке программы. Я не достаточно комфортно с современными загрузчиками говорю, правда это или нет.

Но если вы предварительно инициализируете его, то его обязательно нужно будет загрузить из исполняемого файла.

Учтите, что ни один из них не оказывает «реального» влияния на производительность в малом. Их может и не быть в «большом». Просто говорю, что здесь есть потенциал, и эти две техники на самом деле делают что-то совершенно другое.

-1
ответ дан 28 November 2019 в 22:56
поделиться

Я очень предпочитаю

char buffer[1024] = { 0 };

Он короче, легче читается и менее подвержен ошибкам. Используйте memset только для динамически выделяемых буферов, а затем предпочитайте calloc .

12
ответ дан 28 November 2019 в 22:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: