Не является прямым решением, но в целом я счел целесообразным переместить как можно больше выделения из статического времени инициализации. Обычно это приводит к головным болям (порядок инициализации, порядок инициализации и т. Д.).
Если это слишком сложно, вы можете вызвать _CrtMemCheckpoint
( http://msdn.microsoft.com/en- us / library / h3z85t43% 28VS.80% 29.aspx ) в начале main()
и _CrtMemDumpAllObjectsSince
в конце.
Цитировать эту статью https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
Ограничение максимальной длины пути
В Windows API (с некоторыми исключениями, обсуждаемыми в следующих параграфах), максимальная длина пути составляет MAX_PATH , который определяется как 260 символов. Локальный путь структурируется в следующем порядке: буква диска, двоеточие, обратная косая черта, компоненты имен, разделенные обратной косой чертой, и завершающий нулевой символ. Например, максимальный путь на диске D равен «D: \ , строка пути длиной 256 символов < NUL>», где «< NUL>» представляет невидимый завершающий нулевой символ для текущей системной кодовой страницы. (Символы <> используются здесь для наглядности и не могут быть частью допустимой строки пути.)
Теперь мы видим, что это 1 + 2 + 256 + 1 или [диск] [ : \] [path] [null] = 260. Можно предположить, что 256 - это разумная фиксированная длина строки из дней DOS. Возвращаясь к API DOS, мы понимаем, что система отслеживала текущий путь на диск, и у нас есть 26 (32 с символами) максимум дисков (и текущие каталоги).
INT 0x21 AH = 0x47 говорит: «Эта функция возвращает описание пути без буквы диска и начальной обратной косой черты». Итак, мы видим, что система сохраняет CWD в виде пары (диск, путь), и вы запрашиваете путь указав диск (1 = A, 2 = B,…), если вы укажете 0, то он принимает путь для диска, возвращенный INT 0x21 AH = 0x15 AL = 0x19. Итак, теперь мы знаем, почему это 260, а не 256, потому что эти 4 байта не хранятся в строке пути.
Почему 256-байтовая строка пути, потому что 640 КБ достаточно ОЗУ.
Это не совсем так, поскольку файловая система NTFS поддерживает пути длиной до 32 тыс. Символов. Вы можете использовать API-интерфейс win32 и префикс пути «\\?\
», чтобы использовать более 260 символов.
Подробное объяснение длинного пути из блога .Net BCL team .
Небольшая выдержка подчеркивает проблему с длинными путями
Еще одной проблемой является непоследовательное поведение, которое может возникнуть в результате предоставления поддержки длинных путей. Длинные пути с префиксом
\\?\
могут использоваться в большинстве файловых API Windows, но не во всех Windows API. Например, LoadLibrary, который отображает модуль на адрес вызывающего процесса, завершается ошибкой, если имя файла длиннее, чем MAX_PATH. Таким образом, это означает, что MoveFile позволит вам переместить библиотеку DLL в такое место, где ее путь будет длиннее 260 символов, но при попытке загрузить библиотеку DLL произойдет сбой. Есть аналогичные примеры в Windows API; Существуют некоторые обходные пути, но они применяются в каждом конкретном случае.
Вопрос в , почему ограничение все еще существует. Конечно, современные Windows могут увеличить сторону MAX_PATH
, чтобы позволить более длинные пути. Почему ограничение не было снято?
Благодаря API-контракту Windows гарантировала всем приложениям, что стандартные файловые API никогда не будут возвращать путь, длина которого превышает 260
символов.
Рассмотрим следующий правильный код:
WIN32_FIND_DATA findData;
FindFileFirst("C:\Contoso\*", ref findData);
Windows гарантировала моей программе, что она заполнит мою WIN32_FIND_DATA
структуру:
WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
//...
TCHAR cFileName[MAX_PATH];
//..
}
Мое приложение не объявляло значение константы MAX_PATH
, это сделал Windows API. Мое приложение использовало это определенное значение.
Моя структура правильно определена и выделяет всего 592
байт. Это означает, что я могу получить только имя файла, длина которого меньше 260
символов. Windows пообещала мне, что если я напишу свое приложение правильно, мое приложение продолжит работать в будущем.
Если бы Windows разрешала имена файлов длиннее 260
символов, то мое существующее приложение (которое правильно использовало правильный API) не работало бы.
Для тех, кто призывает Microsoft изменить константу MAX_PATH
, сначала необходимо убедиться, что ни одно из существующих приложений не дает сбой. Например, я все еще владею и использую приложение Windows, которое было написано для работы в Windows 3.11. Он по-прежнему работает на 64-битной Windows 10. Это то, что дает вам обратная совместимость.
Microsoft создала способ использования полных 32 768 путей; но они должны были создать новый контракт API для этого. Например, вы должны использовать Shell API для перечисления файлов (поскольку не все файлы существуют на жестком диске или в сетевой папке).
Но они также не должны ломать существующие пользовательские приложения. Подавляющее большинство приложений не используют API оболочки для работы с файлами. Все просто звонят FindFirstFile
/ FindNextFile
и называют это днем.
В Windows 10. вы можете снять ограничение , изменив ключ реестра.
Подсказка Начиная с Windows 10, версия 1607, ограничения MAX_PATH были удалены из общих функций файлов и каталогов Win32. Однако вы должны подписаться на новое поведение.
Раздел реестра позволяет вам включить или отключить новое поведение длинного пути. Чтобы включить поведение длинного пути, установите ключ реестра в
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled
(Тип:REG_DWORD
). Значение ключа будет кэшироваться системой (для каждого процесса) после первого вызова уязвимой функции файла или каталога Win32 (список следует). Раздел реестра не будет перезагружен в течение всего жизненного цикла процесса. Чтобы все приложения в системе могли распознать значение ключа, может потребоваться перезагрузка, поскольку некоторые процессы могли быть запущены до того, как ключ был установлен. Раздел реестра также можно контролировать с помощью групповой политики наComputer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths
. Вы также можете включить новое поведение длинного пути для приложения через манифест:<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> </windowsSettings> </application>
Один из способов справиться с ограничением пути состоит в сокращении записей пути с помощью символических ссылок.
Например:
C:\p
для хранения коротких ссылок на длинные пути mklink /J C:\p\foo C:\Some\Crazy\Long\Path\foo
C:\p\foo
к вашему пути вместо длинного пути Что касается , почему это все еще существует - MS не считает это приоритетом и ценит обратную совместимость по сравнению с продвижением своих ОС (по крайней мере, в этом случае).
Обходной путь, который я использую, состоит в том, чтобы использовать «короткие имена» для каталогов в пути, вместо их стандартных, удобочитаемых версий. Так например для C:\Program Files\
я бы использовал C:\PROGRA~1\
. Вы можете найти эквиваленты короткого имени, используя dir /x
.
Что касается того, как справиться с ограничением размера пути в Windows - использование 7zip для упаковки (и распаковки) ваших файлов, чувствительных к длине пути, кажется приемлемым обходным путем. Я использовал его для переноса нескольких инсталляций IDE (эти пути к подключаемым модулям Eclipse, yikes!) И груды автоматически сгенерированной документации, и до сих пор не было ни одной проблемы.
Не совсем уверен, как он уклоняется от ограничения в 260 символов, установленного Windows (из технической точки зрения), но эй, это работает!
Более подробная информация на их странице SourceForge здесь :
«NTFS может фактически поддерживать имена путей длиной до 32 000 символов.»
7 -zip также поддерживает такие длинные имена.
Но это отключено в коде SFX. Некоторым пользователям не нравятся длинные пути, так как они не понимают, как с ними работать. Вот почему я отключил его в коде SFX.
9.32 alpha 2013-12-01
- Улучшена поддержка имен файлов длиннее 260 символов .
4.44 beta 2007-01-20
- 7-Zip теперь поддерживает имена файлов длиннее 260 символов.
ВАЖНОЕ ПРИМЕЧАНИЕ: Чтобы это работало правильно, вам нужно указать путь назначения в диалоговом окне «Извлечь» 7zip напрямую, а не перетаскивание & amp; сбросив файлы в нужную папку. В противном случае папка «Temp» будет использоваться в качестве промежуточного кэша, и вы попадете в то же ограничение в 260 символов, как только Windows Explorer начнет перемещать файлы в их «окончательное место покоя». См. Ответы на на этот вопрос для получения дополнительной информации.
Вы можете включить длинные имена путей с помощью PowerShell:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1
Другая версия заключается в использовании групповой политики в Computer Configuration
/ Administrative Templates
/ System
/ Filesystem
:
Это так, и по какой-то причине это значение по умолчанию, но вы можете легко переопределить его с помощью этого ключа реестра:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001
Еще один способ справиться с этим - использовать Cygwin, в зависимости от того, что вы хотите сделать с файлами (то есть, если команды Cygwin удовлетворяют вашим потребностям)
Например, он позволяет копировать, перемещать или переименовывать файлы, которые даже Windows Explorer не может. Или, конечно, иметь дело с их содержимым, таким как md5sum, grep, gzip и т. Д.
Также для программ, которые вы кодируете, вы можете связать их с Cygwin DLL, и это позволит им использовать длинные пути (хотя я не проверял это, хотя)
Вы можете смонтировать папку как диск. Из командной строки, если у вас есть путь C:\path\to\long\folder
, вы можете сопоставить его с буквой диска X:
, используя:
subst x: \path\to\long\folder