Ошибка связывания при сборке без встроенных функций CRT, memcpy и memset

Я пытаюсь создать приложение как можно меньшего размера и при этом стараюсь избегать использования CRT, используя вызовы Win API вместо стандартных вызовов C / C ++. К сожалению, я все еще получаю единственную ошибку компоновщика:

Error   2   error LNK2001: unresolved external symbol _memcpy

Я нигде в своем коде не вызываю memcpy, поэтому предполагаю, что его вызывает одна из функций Windows. Включение встроенных функций дает неразрешенный символ _memset, который я тоже не использую. Насколько я понимаю, и memcpy, и memset должны быть включены с включенными встроенными функциями. Поскольку мой код слишком длинный для публикации, вот вызовы Win API в моей программе:

  • lstrcpy
  • wsprintf
  • CopyMemory - ошибка переключается на _memset, когда я закомментировал это
  • OpenFileMapping
  • MapViewOfFile
  • CreateFileMapping

Мои вопросы:

  • Почему не включены внутренние функции, если у меня объявлен / Oi?
  • Do I need to declare memset and memcpy on my own?
    • If so, how do I do so without Visual Studio complaining of redefinition of intrinsic functions?

person Knox    schedule 27.01.2014    source источник
comment
Оптимизатор кода легко заменяет циклы for (;;) вызовами memcpy или memset. Вы должны предоставить для них реализацию.   -  person Hans Passant    schedule 27.01.2014
comment
Я их просто написал, и это сработало :). Однако мне все еще любопытно, почему они не включены как внутренние функции, если я установил / Oi. Я впервые делаю что-то подобное. Может быть, вы (или кто-то еще) могли бы объяснить?   -  person Knox    schedule 27.01.2014


Ответы (3)


/Oi не задокументирован как обязательная вставка всех встроенных функций, где это возможно, вместо этого он просто дает компилятору возможность сделать это. Мне не удалось выяснить, какую логику использует MSVC для окончательного вывода, но некоторые факторы включают режим проекта (гораздо более вероятно, что встроенные функции в RELEASE будут внедрены в RELEASE по сравнению с DEBUG) и длину ваших функций.

Последние версии Visual Studio действительно интегрировали зависимости MSVCRT в компилятор, и становится все труднее генерировать код, не зависящий от стандартной среды выполнения C.

Стандартный способ решения этих проблем (хотя Microsoft чрезвычайно не одобряет этого) - установить ссылку на системную копию MSVCRT.dll, которая поставляется в той или иной форме Со всеми версиями винды. Пока вы используете стандартные функции C, такие как memset, вы можете спокойно игнорировать пронзительные взгляды Microsoft неодобрения и ссылаться на то, что вам нравится, но не пытайтесь использовать его для более сложных функций и API, предоставляемых CRT.

Чтобы связать с msvcrt.dll, вам нужно либо использовать LoadLibrary и co, либо использовать предварительно сгенерированный msvcrt.lib (Microsoft намеренно не предоставляет его), чтобы сообщить MSVC, какие функции доступны в системе MSCRT.dll


Обновление: теперь мы публикуем предварительно созданные mscvrt.lib файлы для статической связи с CRT (на ваш страх и риск!) Для платформ x86 и x64: https://github.com/neosmart/msvcrt.lib

person Mahmoud Al-Qudsi    schedule 13.10.2017
comment
Для функций mem * и str * GCC, кажется, оптимизируется с помощью '_builtin' в основном, когда размер постоянный (известный во время компиляции). MSVC, вероятно, ведет себя аналогичным образом. - person duanev; 07.08.2019

memset() исходит от ZeroMemory()

Нажав на это, я просто ввел канонические определения memcpy, memmove, memset из "Языка программирования C".

person Joshua    schedule 07.11.2017

Вы не можете избежать ссылки на CRT. Однако, чтобы уменьшить размер вашего EXE, вы можете установить статическую ссылку на CRT. Компоновщик удалит весь ненужный код CRT, поэтому ваше приложение будет как можно меньше. И ошибок компоновщика не будет.

person OlegKrivtsov    schedule 27.01.2014
comment
Вы можете избегать связывания со средой выполнения VC, как динамически, так и статически, как я делал это время от времени. Нативные приложения или библиотеки DLL только для WIN32API не являются чем-то необычным, и хотя бывают случаи, когда они полезны, они бывают редко. Вы не получите некоторых существенных преимуществ, но это возможно. - person WhozCraig; 27.01.2014
comment
WhozCraig прав. Но это непросто. Если вы попытаетесь это сделать, будьте готовы к устранению ошибок компоновщика, проблем с производительностью и других осложнений. Я нашел это очень полезным. - person walkingTarget; 11.12.2014