Недавно я упоминал здесь общие правила:
Слишком длинный список аргументов в make-файле
Работающая реализация этого правила есть у меняlibfind
:https://sourceforge.net/p/schillix-on/schillix-on/ci/default/tree/usr/src/lib/libfind/find.c#l2020
Основная проблема здесь заключается в том, что libfind
нужно знать текущий размер среды и является ли вызываемая программа 32-битной или 64-битной, поскольку существуют разные ограничения....
libfind
делает это различие между 32 и 64 битами, потому что раньше я часто достигал предела при вызове find -name '*.c' -exec count -t {} +
, чтобы получить количество строк исходного кода для больших проектов, когда libfind
использовался из 64-битной оболочки при вызове 32-битного count
.
В реализации Solaris find
нет необходимости делать это различие, так как Solaris не поставляет 64-битный поиск и, таким образом, использование 32-битного ограничения будет работать в любом случае -, даже если не используется максимальное возможный размер списка аргументов.
Кстати, :для find
маловероятно, что применяется ненужный дополнительный предел для одного аргумента в Linux (128k ). Для make
это настоящая проблема, поскольку вся командная строка оболочки передается как один аргумент. С другой стороны, make
не выполняет предварительную проверку, поскольку make
не содержит кода для разделения длинных команд.
П.С. :Я только что обнаружил забавное ограничение на Solaris :, и xargs
, и find
из Solaris вызывают свои программы через execvp()
из libc
, и в случае, если вызываемая программа является скриптом без #!
, execvp()
Реализация вызывает оболочку для сценария и переупорядочивает аргументы, используя массив фиксированного размера. Поскольку в этом массиве всего 255 записей, аргументы xargs
и find
ограничены 255, если команда представляет собой такой простой сценарий оболочки. Если программа представляет собой такой сценарий, а список аргументов содержит более 255 аргументов, execvp()
вернет E2BIG
.
Проблема в том, что :вы не можете использовать malloc()
внутри execvp()
, так как execvp()
мог быть вызван из процесса, созданного с помощью vfork()
. Если execvp()
вызовет malloc()
, это приведет к мертвой выделенной памяти в родительском... вызов alloca()
на другой стороне всегда будет успешным, но может привести к SIGSEGV
в случае превышения размера локального стека..
Перезагрузка устранила проблему. Я волновался, что если загрузчику понадобится место на диске, я не смогу перезагрузиться, поэтому я сохранил его на крайний случай. Однако это сработало. Обратите внимание, что это было после удаления некоторых файлов вручную через rm
.