Как перевыделение и memcpy работают?

фатальная ошибка: неожиданно найден nil при распаковке необязательного значения

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

Например,

var tempVar: String?
print(tempVar!)

tempVar не инициализирован, поэтому приложение отключается в этом случае, поэтому вам нужно использовать

print(tempVar ?? "") 

. См. Необязательный цепочка для более подробной информации

24
задан Sourav Ghosh 23 December 2016 в 15:14
поделиться

7 ответов

1 - Нет. Они копируют блок за один раз. См. http://www.embedded.com/design/configurable-systems/4024961/Optimizing-Memcpy-improves-speed для довольно хорошего анализа.

2 - Это является зависящим от реализации. См. http://www.gnu.org/software/libtool/manual/libc/Changing-Block-Size.html для деталей glibc. "В нескольких реализациях выделения, делая блок меньшим иногда требует копировать его"

19
ответ дан Sean 28 November 2019 в 23:15
поделиться

Давайте бросим немного более внимательного взгляда на memcpy и, в то время как мы в нем в "большом O" или нотации Landau.

Первый, большой-O. Поскольку я говорил о в другом месте, стоит помнить определение большого O, который является, что некоторая функция г (n) , как говорят, O (f (n)) , когда там существует константа k для который г (n) kf (n) . То, что делает константа, позволяет Вам проигнорировать небольшие детали в пользу важной части. Как все отметили, memcpy из [1 112] n , байты будут O (n) в большей части любой нормальной архитектуры, потому что, неважно, что необходимо переместить те n байты, один блок за один раз. Так, первая, наивная реализация memcpy в C могла быть записана

unsigned char *
memcpy(unsigned char * s1, unsigned char * s2, long size){
    long ix;
    for(ix=0; ix < size; ix++)
        s1[ix] = s2[ix];
    return s1;
}

, Это на самом деле O (n) и могло бы заставить Вас задаться вопросом, почему мы даже беспокоимся библиотечной подпрограммой. однако, вещь о libc функционирует, то, что они - место, где определенные для платформы утилиты записаны; если Вы хотите оптимизировать для архитектуры, это - одно из мест, можно сделать это. Так, в зависимости от архитектуры , может быть более эффективное внедрение опции; например, в IBM 360 archiecture, существует MOVL инструкция, что данные перемещений являются большими блоками, использующими очень высоко оптимизированный микрокод. Таким образом вместо того цикла, 360 реализаций memcpy могли бы вместо этого посмотреть что-то как [1 129]

LR 3,S1      LOAD S1 ADDR in Register 3
LR 4,S2      
MOVL 3,4,SIZE

(Никакие гарантии, это - точно правильные 360 кодов между прочим, но это будет служить для иллюстрации.) Эта реализация взгляды как вместо того, чтобы делать , который сделали шаги n вокруг цикла как код C, это просто выполняет 3 инструкции.

то, Что действительно происходит, тем не менее, - то, что это выполняется O (n) микро инструкции под покрытиями. То, что является отличающееся между этими двумя, является константой k; потому что микрокод намного быстрее, и потому что существует, только три декодируют шаги на инструкциях, это существенно быстрее, чем наивная версия, но это все еще O (n) - это - просто константа, меньше.

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

18
ответ дан Charlie Martin 28 November 2019 в 23:15
поделиться
  1. нет абсолютно никакого способа скопировать объекты N быстрее, чем O (N). Однако это могло бы быть в состоянии скопировать несколько объектов сразу или использовать специальные инструкции по процессору - таким образом, это все еще могло бы быть быстрее, чем Вы могли сделать это сами.
  2. я не знаю наверняка, но я предположил бы, что память полностью перераспределена. Это - самое безопасное предположение, и это является, вероятно, зависящим от реализации так или иначе.
5
ответ дан Mark Ransom 28 November 2019 в 23:15
поделиться
  1. производительность memcpy не может действительно быть лучше, чем O (N), но это может быть оптимизировано так, чтобы это превзошло ручное копирование по характеристикам; например, это могло бы быть в состоянии скопировать 4 байта во время, это берет Вас для копирования 1 байта. Многие memcpy реализации записаны в блоке с помощью оптимизированных инструкций, которые могут скопировать несколько элементов за один раз, который обычно быстрее, чем копирование данных один байт за один раз.

  2. я не вполне понимаю этот вопрос, если Вы будете использовать realloc для уменьшения размера памяти, и это успешно выполняется (непустой указатель возвратов), новое местоположение будет содержать те же данные как старое местоположение до размера нового запроса. Если ячейка памяти была изменена в результате вызова realloc (не обычный при уменьшении размера), содержание будет скопировано, иначе никакого копирования не должно происходить, поскольку память не переместилась.

5
ответ дан Robert Gamble 28 November 2019 в 23:15
поделиться
  1. можно предугадать, что memcpy мог быть записан таким образом, что это переместит большое количество битов вокруг. например, совершенно возможно скопировать данные с помощью инструкций SSE, если это выгодно.

Как другой сказанный, это не будет быстрее, чем O (n), но системы памяти часто имеют предпочтительный размер блока, и также возможно, скажем, записать размер строки кэша за один раз.

2
ответ дан Calyth 28 November 2019 в 23:15
поделиться

Предположение Вас говорит о glibc, и так как Ваши вопросы являются зависящими от реализации, вероятно, лучше только проверить источник:

malloc.c

memcpy.c

путем я считал его, ответы будут:

  1. O (N)---нет никакого способа скопировать объекты в лучше, чем линейное время.
  2. Иногда большие объекты будут скопированы, когда перевыделение () будет использоваться для уменьшения их.
0
ответ дан Nathan Kurz 28 November 2019 в 23:15
поделиться

x86 имеет специальные инструкции для сканирования и соответствия байту/слову в блоке памяти также и той, которая может использоваться для копирования блока памяти (это - CPU CISC, в конце концов). Много компиляторов C, которые реализуют язык встроенного ассемблерного кода и прагму, чтобы сделать встраивание целых функций, имеет для многих много лет, использованных в своих интересах это в их библиотечных функциях.

Те используемые для копии мадам являются movsb/movsw в комбинации к инструкции представителя.

CMPS/MOVS/SCAS/STOS
REP, REPE, REPNE, REPNZ, REPZ

Установочные регистры с адресами src/trg и интервалом рассчитывают, и далеко Вы идете.

0
ответ дан RogerV 28 November 2019 в 23:15
поделиться
Другие вопросы по тегам:

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