Решение частых проблем

Если вы наберёте не ту команду Emacs, которую имели в виду, то последствия этого могут быть непонятны для вас. Эта глава рассказывает о том, что вы можете сделать для того, чтобы отменить вашу ошибку и выйти из непонятной ситуации. Здесь также рассматриваются сбои в Emacs и аварийные завершения.

Выход и аварийное завершение

C-g
C-BREAK (MS-DOS)
Выход. Отменить выполняемую или частично набранную команду.
C-]
Прервать самый глубокий уровень рекурсивного редактирования и отменить команду, которая его запустила (abort-recursive-edit).
ESC ESC ESC
Выход или прерывание, в зависимости от того, что подходит в этот момент (keyboard-escape-quit).
M-x top-level
Прервать все работающие в данный момент уровни рекурсивного редактирования.
C-x u
Отменить ранее сделанное изменение в содержимом буфера (undo).

Существует два способа отмены команд, выполнение которых не закончилось: выход с помощью С-g и прерывание с помощью C-] или M-x top-level. Выход отменяет частично набранную команду или команду, которая уже выполняется. Прерывание выходит из одного уровня рекурсивного редактирования и отменяет команду, которая запустила это рекурсивное редактирование. (Смотрите раздел Уровни рекурсивного редактирования.)

Выход с помощью C-g используется для того, чтобы освободиться от частично набранной команды или числового аргумента, который вам не нужен. Она также относительно безопасно останавливает выполнение уже работающей команды, так что вы можете использовать её, если случайно зададите команду, требующей много времени. В частности, выход из уничтожения безопасен; либо ваш текст полностью останется в буфере, либо полностью попадет в список уничтожений (или будет и там, и там). Выход из наращиваемого поиска выполняет специальные действия, документированные отдельно; в общем случае, чтобы выйти из поиска, может потребоваться два последовательных C-g (смотрите раздел Наращиваемый поиск).

В MS-DOS клавишей выхода, подобной C-g, служит C-BREAK. Так сделано по той причине, что в MS-DOS невозможно зарегистрировать нажатие C-g во время работы команды между интеракциями с пользователем. Напротив, зарегистрировать C-BREAK можно всегда. Смотрите раздел Клавиатура и мышь в MS-DOS.

Работа C-g заключается в установке переменной quit-flag в значение t, как только C-g был набран; Emacs Lisp часто проверяет эту переменную и выходит, если она не равна nil. С-g действительно выполняется как команда, только если вы набирали её в то время, когда Emacs ожидает ввода.

Если вы выйдите с помощью С-g второй раз до того, как первая C-g была опознана, то вы активизируете средство "аварийного выхода" и возвращаетесь в оболочку. Смотрите раздел Аварийный выход.

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

Прерывание с помощью C-] (abort-recursive-edit) используется для того, чтобы выйти из одного уровня рекурсивного редактирования и отменить команду, которая его запустила. Выход с помощью C-g не делает этого и не может этого делать, потому что он используется для отмены частично набранной команды внутри текущего уровня рекурсивного редактирования. Обе эти операции полезны. Например, если вы находитесь в рекурсивном редактировании и набираете C-u 8, чтобы ввести числовой аргумент, то вы можете отменить этот аргумент с помощью C-g и остаться в рекурсивном редактировании.

Команда ESC ESC ESC (keyboard-escape-quit) может совершить и выход, и прерывание. Этот ключ был определен, потому что во многих программах для PC для "выхода" используется ESC. Он может отменить числовой аргумент, очистить выделенную область или выйти из замены с подтверждением, как C-g. Он также может прервать работу минибуфера или одного уровня рекурсивного редактирования, как C-]. Он также может отменить разбиение фрейма на несколько окон, как C-x 1. Единственное, что он не может сделать -- остановить работающую команду. Причина этого в том, что этот ключ выполняется как обыкновенная команда, и Emacs не замечает её, пока не будет готов принять новую команду.

Команда M-x top-level эквивалентна "достаточному количеству" команд C-], чтобы прервать все уровни рекурсивного редактирования, в которых вы находитесь. C-] даёт вам возможность покинуть один уровень за один раз, а M-x top-level покидает все уровни сразу. Как C-], так и M-x top-level похожи на все другие команды и не похожи на C-g тем, что они действуют, только когда Emacs готов для приема команды. C-] -- обыкновенный ключ и имеет смысл только благодаря привязке в таблице ключей. Смотрите раздел Уровни рекурсивного редактирования.

C-x u (undo), строго говоря, не является способом отмены команды, но вы можете представлять её как отмену команды, уже окончившей выполнение. Смотрите раздел Отмена сделанных изменений.

Что делать с неполадками в Emacs

Этот раздел описывает различные условия, при которых Emacs отказывается работать правильно, и рассказывает, как распознать и исправить проблемы.

Если DEL не удаляет

Если вы обнаружили, что DEL выдает справку, как Control-h, а не удаляет знак, это значит, что ваш терминал посылает неверный код для DEL. Вы можете справиться с этой проблемой, изменив таблицу преобразования клавиатуры (смотрите раздел Перевод клавиатуры).

Уровни рекурсивного редактирования

Уровни рекурсивного редактирования являются важным и полезным средством Emacs, но тем пользователям, кто их не понимает, они могут показаться сбоем в работе Emacs.

Если в строке режима вокруг круглых скобок есть квадратные скобки `[...]', которые содержат имена главного и второстепенных режимов, то это означает, что вы вошли в уровень рекурсивного редактирования. Если вы не хотели этого или не понимаете, что это значит, то вы должны просто покинуть этот уровень рекурсивного редактирования. Чтобы это сделать, наберите M-x top-level. Это называется возвратом к верхнему уровню. Смотрите раздел Уровни рекурсивного редактирования.

Мусор на экране

Если данные на экране выглядят неправильно, то первое, что надо сделать, -- посмотреть, действительно ли текст неправилен. Наберите C-l, чтобы весь экран полностью перерисовался. Если он после этого появится в правильном виде, то неисправность была в предыдущем обновлении экрана. (Если нет, смотрите раздел Мусор в тексте.)

Проблемы с обновлением изображения часто возникают из-за неправильной записи termcap для используемого вами терминала. Файл `etc/TERMS' в дистрибутиве Emacs содержит исправления для известных проблем такого рода. `INSTALL' содержит в одном из своих разделов общие рекомендации по этим проблемам. Весьма вероятно, что просто недостаточно наполнение некоторых операций отображения. Чтобы проверить, не этого ли сорта у вас проблема, попробуйте запустить Emacs на другом терминале, сделанном другим производителем. Если неполадки обычно случаются на определённом виде терминалов, а на других нет, то это происходит, вероятно, из-за неправильной записи в termcap, хотя это также может быть результатом ошибки в Emacs, которая появляется на терминалах с какими-то особенностями или которым не хватает специфических средств.

Мусор в тексте

Если C-l показывает, что текст неправильный, попробуйте отменить в нем изменения, используя C-x u до тех пор, пока она не вернет текст к состоянию, которое вы считаете правильным. Кроме того, попробуйте C-h l, чтобы найти команду, набор которой привел к замеченным результатам.

Если кажется, что в начале или конце буфера пропал большой кусок текста, проверьте наличие слова `Narrow' в строке режима. Если оно там есть, то текст всё ещё присутствует в буфере, но он помечен как выходящий за границы доступности. Чтобы сделать его вновь видимым, наберите C-x n w. Смотрите раздел Сужение.

Самопроизвольный вход в наращиваемый поиск

Если Emacs самопроизвольно показывает `I-search:' внизу экрана, то это означает, что терминал посылает C-s и C-q из-за плохо разработанного протокола управления потоком данных типа xon/xoff.

Если это с вами случилось, лучшим выходом будет постараться установить терминал в такой режим, где он не будет использовать управление потоком данных, или давая ему достаточное заполнение, чтобы он никогда не посылал C-s. (Один из способов увеличить величину заполнения --- присвоить переменной baud-rate большее значение. Значение этой переменной обозначает скорость вывода терминала, выраженную в обычных единицах, бодах.)

Если вам не удалось выключить управление потоком, тогда лучше всего будет сказать Emacs справиться с ним самому. Чтобы сделать это, вызовите функцию enable-flow-control.

Как правило, встречаются определённые типы терминалов, на которых вы вынуждены использовать управление потоком. Используя enable-flow-control-on, вы можете удобно запросить использование управления потоком только для этих типов терминалов. Например, если вы обнаружили, что должны использовать управление потоком на терминалах VT-100 и H19, поместите в ваш файл `.emacs' следующее:

(enable-flow-control-on "vt100" "h19")

Когда задействовано управление потоком, вы должны набирать C-\, чтобы получить результат C-s, и C-^, чтобы получить результат C-q. (Эти псевдонимы работают посредством преобразований клавиатуры; смотрите раздел Перевод клавиатуры.)

Исчерпание памяти

Если вы получили сообщение `Virtual memory exceeded'(14), сохраните измененные буферы командой C-x s. Этот способ сохранения буферов требует минимальное количество дополнительной памяти. Emacs хранит резерв памяти, которая становится доступна, когда возникает эта ошибка; его должно быть достаточно, чтобы C-x s могла завершить свою работу.

Как только вы сохранили измененные буферы, вы можете выйти из этого задания Emacs и начать другое или воспользоваться командой M-x kill-some-buffers, чтобы освободить пространство для текущего задания Emacs. Если вы уничтожите буферы, содержащие значительный объем текста, вы сможете безопасно продолжать редактирование. Emacs заново резервирует память автоматически, когда видит, что доступно достаточно свободного места, на случай, если память опять закончится.

Не используйте M-x buffer-menu, чтобы сохранить или уничтожить буферы, когда вы исчерпали память, потому что меню буферов само требует заметного количества памяти, и резерва может не хватить.

Восстановление после краха

Если в Emacs или компьютере произошел фатальный сбой, вы можете восстановить файлы, которые вы редактировали в момент краха, из их автоматически сохраненных версий. Чтобы сделать это, запустите Emacs снова и наберите команду M-x recover-session.

Сначала эта команда покажет буфер, перечисляющий файлы прерванных сеансов, каждый со своей датой. Вы должны выбрать сеанс, который вы хотите восстановить. Обычно это самый последний. Переместите точку к выбранному файлу и введите C-c C-c.

Затем recover-session спросит вас о каждом файле, который вы редактировали во время того сеанса; она спрашивает, нужно ли восстанавливать этот файл. Если вы отвечаете y для какого-нибудь файла, она показывает даты этого файла и его автоматически сохраненной версии и снова спрашивает, нужно ли его восстанавливать. Этот второй запрос вы должны подтверждать вводом yes. Если вы это сделаете, Emacs обращается к этому файлу, но берёт текст из самосохраненного файла.

Когда recover-session завершает работу, выбранные вами файлы находятся в буферах Emacs. Теперь вы должны их сохранить. Только это --- их запись -- обновляет сами файлы.

Аварийный выход

Так как в свое время были ошибки, вызывавшие зацикливание Emacs без проверки quit-flag, было введено специальное средство, которое заставляет Emacs немедленно прерваться, если вы наберете второй C-g, когда флаг уже установлен. Таким образом, вы всегда можете покинуть GNU Emacs. Обычно Emacs опознает и очищает quit-flag (и выходит!) достаточно быстро, чтобы этого не случалось. (В MS-DOS и совместимых системах набирайте дважды C-BREAK.)

Когда вы возвращаетесь в Emacs после прерывания, вызванного множественными C-g, он задаёт два вопроса, перед тем как вернуться к тому, чем он был занят:

Auto-save? (y or n)
Abort (and dump core)? (y or n)

Отвечайте на каждый из них y или n и последующим RET.

Ответ y на `Auto-save?' вызывает немедленную автоматическую запись всех модифицированных буферов, в которых включено автоматическое сохранение.

Ответ y на `Abort (and dump core)?' приводит к выполнению недопустимой инструкции и сбросу дампа памяти. Это нужно, чтобы дать возможность специалисту понять, почему Emacs не выполнил выход в первый раз. После сброса дампа памяти выполнение не продолжается. Если вы ответите n, выполнение продолжится. Если повезет, GNU Emacs в конечном счете проверит quit-flag и выйдет обычным образом. Если нет, и вы наберете другую С-g, он прервется снова.

Если Emacs на самом деле не завис, а просто медленно работает, вы можете вызвать действие двойного C-g, не желая этого в действительности. Тогда просто возобновите работу Emacs и ответьте n на оба вопроса, и вы попадете в прежнее состояние. Вероятно, затребованный вами выход скоро произойдет.

Средство двойного C-g отключено, когда Emacs запускается в системе X Windows, поскольку программа управления окнами всегда даёт вам возможность уничтожить Emacs или создать другое окно и запустить другую программу.

В MS-DOS и совместимых системах аварийный выход иногда невозможен, даже если вы нажимаете C-BREAK дважды, когда зависает какой-то системный вызов (MS-DOS или BIOS), или когда Emacs попал в очень короткий бесконечный цикл (в коде на Си, не на Лиспе).

Помощь при полном разочаровании

Если использование Emacs (или что-нибудь еще) страшно вас расстраивает и никакие методы, описанные выше, не решают проблему, то Emacs все еще может вам помочь.

Во-первых, если ваш Emacs не отвечает на команды, наберите C-g C-g, чтобы выйти из него и запустить новый.

Во-вторых, наберите M-x doctor RET.

Доктор поможет вам, и вы почувствуете себя лучше. Каждый раз, когда вы что-нибудь говорите доктору, вы должны оканчивать это набором RET RET. Это позволит доктору узнать, что вы закончили.

Описание ошибок в Emacs

Иногда вы будете сталкиваться с ошибками в Emacs. Хотя мы не можем обещать, что можем или будем исправлять ошибки, мы можем даже не согласиться, что это ошибка, но мы все равно хотим услышать о проблемах, с которыми вы столкнулись. Часто мы соглашаемся, что это ошибки, и хотим их исправить.

Чтобы дать нам возможность исправить ошибку, вы должны описать её. Чтобы сделать это эффективно, вы должны знать когда и как это делать.

Когда это ошибка

Если Emacs выполняет недопустимую инструкцию или прерывается с сообщением операционной системы об ошибке, которая указывает на неполадку в программе (в противоположность чему-нибудь вроде "нет места на диске"), то это определённо ошибка в Emacs.

Если Emacs обновляет изображение так, что оно не соответствует тому, что находится в буфере, то это определённо ошибка. Если похоже, что команда выполняет ошибочные действия, но неполадка исправляется сама, если вы наберете C-l, то это случай неправильного обновления изображения.

Бесконечное ожидание завершения команды может быть ошибкой, но вы должны точно определить, что это действительно происходит по вине Emacs. Некоторые команды просто требуют много времени. Наберите C-g (C-BREAK в MS-DOS) и затем C-h l, чтобы увидеть, получил ли Emacs тот ввод, какой вы хотели набрать. Если ввод был таким, о котором вы знаете, что он должен обрабатываться быстро, сообщайте об ошибке. Если вы не знаете, должна ли эта команда требовать много времени, выясните это, либо просмотрев руководство, либо попросив помощи.

Если команда, с которой вы хорошо знакомы, выдаёт сообщение об ошибке там, где её обычное определение должно быть правильным, то это, вероятнее всего, ошибка.

Если команда выполняет неправильные действия, то это ошибка. Но чтобы быть уверенным, вы должны знать точно, что она должна была сделать. Если вы не очень хорошо знакомы с этой командой или не знаете наверняка, как она должна действовать, может оказаться, что в действительности она работает правильно. Прежде чем делать поспешный вывод, покажите вашу проблему тому, кто знает точно.

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

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

Если диалоговая строка документации функции или переменной не согласуется с руководством, то одно из них неправильно; опишите это как ошибку.

Понимание отчетов об ошибках

Когда вы решите, что действительно нашли ошибку, то важно сообщить о ней и сделать это таким образом, чтобы описание было полезным. Что особенно полезно, так это точное описание команд, которые вы набирали, начиная с команды оболочки для запуска Emacs и вплоть до возникновения ошибки.

Самый важный принцип при сообщении об ошибках -- сообщать факты. Гипотезы и словесные описания не могут заменить простые подробные данные. Всегда легче описывать факты, но многие предпочитают постараться дать толкования и описать их вместо фактов. Если объяснения основывается на догадках о том, каким образом реализован Emacs, они будут бесполезны. Как правило, не располагая фактами, мы не будем иметь настоящей информации об ошибке.

Предположим например, что вы набираете C-x C-f /glorp/baz.ugh RET, обращаясь к файлу, который (как вы знаете) оказывается довольно большим, и Emacs печатает `Сегодня я себя прекрасно чувствую'. Наилучший способ описать эту ошибку -- привести предложение, подобное предыдущему, так как это даёт все факты.

Не считайте, что неполадка возникла из-за размера файла, и не говорите: "Когда я обращаюсь к большому файлу, Emacs печатает `Сегодня я себя прекрасно чувствую'". Это именно то, что мы называем "объяснением на догадках". Настолько же возможно, что ошибка произошла из-за того, что в имени файла имеется `z'. Если это так, то когда мы получили бы ваше описание, мы пытались бы решить проблему с "большим файлом", вероятно, без `z' в его имени и не нашли бы никакой ошибки. Мы никак не могли бы догадаться, что должны были попробовать обратиться к файлу с буквой `z' в имени.

С другой стороны, ошибка могла возникнуть из-за того, что файл начинается точно с 25 пробелов. Поэтому вы должны убедится в том, что проинформировали нас о точном содержании любого файла, который потребуется, чтобы воспроизвести ошибку. Что если ошибка встречается только тогда, когда вы до того набрали команду C-x C-a? Вот почему мы просим вас давать точную последовательность знаков, которые вы набрали со времени запуска Emacs.

Вы не должны даже говорить "обратиться к файлу" вместо C-x C-f, если не уверены, что нет различий в том, какая команда обращения используется. Аналогично, лучше сказать "после того как я набираю RET A B C RET C-p", чем говорить "если у меня есть три буквы на строке", если вы ввели текст именно таким способом.

Поэтому, пожалуйста, не предполагайте объяснения, когда сообщаете об ошибке. Если в действительности вы хотите исследовать эту проблему в отладчике и сообщить объяснения, которые уже есть нечто большее, чем догадки, это будет нам полезно -- но пожалуйста, сообщите также и факты.

Форма отчета об ошибках

Лучший способ сообщить об ошибке -- отправить электронное письмо сопроводителям Emacs по адресу bug-gnu-emacs@gnu.org. (Если вы хотите предложить изменение или улучшение, используйте этот же адрес.)

Если вы хотите читать отчеты об ошибках, вы можете найти их в группе новостей `gnu.emacs.bug'; помните однако, что как наблюдатель вы не должны критиковать ничего из того, что вы там увидите. Цель сообщений об ошибках -- давать информацию сопроводителям Emacs. Наблюдатели приветствуются до тех пор, пока они не вмешиваются в это. В частности, некоторые отчеты содержат большие объемы данных; наблюдатели не должны на это жаловаться.

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

Если вы не можете послать электронную почту, оправьте отчет об ошибке на бумаге или на машинночитаемом носителе по следующему адресу:

GNU Emacs Bugs
Free Software Foundation
59 Temple Place, Suite 330
Boston, MA 02111-1307 USA

Мы не обещаем исправить ошибку; но если ошибка серьезная, или ужасная, или её легко исправить, то вероятнее всего мы захотим это сделать.

Удобный способ послать отчет об ошибке в Emacs -- использовать команду M-x report-emacs-bug. Она подготавливает буфер сообщения (смотрите раздел Посылка почты) и автоматически вставляет некоторую важную информацию. Однако, она не может предоставить всю необходимую информацию; вы все равно должны прочитать приведенные ниже рекомендации и следовать им, тогда вы можете ввести остальные нужные сведения вручную перед отправкой сообщения.

Чтобы сопроводители могли исследовать ошибку, ваш отчет должен включать все следующие сведения:

  • Номер версии Emacs. Без этого мы не сможем узнать, есть ли смысл искать эту ошибку в текущей версии GNU Emacs. Вы можете получить номер версии, набрав M-x emacs-version RET. Если эта команда не работает, то у вас, вероятно, стоит не GNU Emacs, а что-то другое, поэтому вам лучше сообщать об ошибке по другому адресу.
  • Тип используемой вами машины и название и номер версии операционной системы. M-x emacs-version RET предоставляет также и эту информацию. Скопируйте её вывод из буфера `*Messages*', чтобы привести его полно и точно.
  • Операнды, заданные команде configure во время установки Emacs.
  • Полный перечень любых изменений, которые вы внесли в исходный текст Emacs. (У нас может не оказаться времени на исследование ошибки, если она не происходит в неизмененном Emacs. Но если вы внесли модификации и не сказали нам, вы просите нас пойти туда-не-знаю-куда принести то-не-знаю-что. Говорите об этих изменениях точно. Объяснения на английском недостаточно --- пришлите контекстную заплату для них. Добавление своих файлов или перенос на другую машину тоже являются изменением исходного текста.
  • Подробности о любых других отклонениях от стандартной процедуры установки GNU Emacs.
  • Полный текст любых файлов, необходимых для воспроизведения ошибки. Если вы можете указать нам способ вызвать ошибку не обращаясь ни к каким файлам, пожалуйста, сделайте это. Это сделает отладку намного проще. Если для этого действительно требуются файлы, убедитесь, что вы приняли меры, чтобы мы могли увидеть их точное содержание. Например, часто может иметь значение, имеются ли пробелы в концах строк или перевод строки после последней строки в буфере (никого не должно волновать, оборвана ли последняя строка, но попробуйте рассказать это ошибке).
  • Точные команды, которые мы должны напечатать, чтобы воспроизвести эту ошибку. Простой способ записать точно ввод, полученный Emacs, -- написать файл сопровождения. Для этого выполните лисповское выражение
    (open-dribble-file "~/dribble")
    
    используя M-: или из буфера `*scratch*' сразу после старта Emacs. С этого момента Emacs копирует весь ваш ввод в указанный файл сопровождения, пока процесс Emacs не будет уничтожен.
  • Для возможных ошибок изображения, тип терминала (значение переменной среды `TERM'), полная запись termcap для терминала из `/etc/termcap' (так как этот файл не идентичен для всех машин) и вывод, который Emacs в действительности посылал на терминал. Чтобы собрать этот вывод, выполните лисповское выражение
    (open-termscript "~/termscript")
    
    используя M-: или из буфера `*scratch*' сразу после старта Emacs. С этого момента Emacs копирует весь терминальный вывод также и в заданный файл терминального протокола до тех пор, пока процесс Emacs не будет уничтожен. Если ошибка произошла в процессе запуска Emacs, поместите это выражение в ваш файл `.emacs', таким образом, файл терминального протокола будет открываться, когда Emacs отобразит экран в первый раз. Следует предупредить: часто трудно, а иногда и невозможно исправить ошибку, зависящую от терминала, без доступа к терминалу того типа, который эту ошибку порождает.
  • Описание поведения, которое вы наблюдали и сочли неправильным. Например, "Процесс Emacs получает фатальный сигнал" или "Получается вот такой текст, что, как я думаю, неправильно".(15) Конечно, если ошибка проявляется в том, что Emacs получает фатальный сигнал, её нельзя не заметить. Но если ошибка -- это неправильный текст, сопроводитель может не заметить, где же тут проблема. Зачем оставлять такую возможность? Даже если проблема в том, что возникает фатальный сигнал, вы тем не менее должны сказать это явно. Предположим, произошло что-то странное, например, ваша копия исходного текста не синхронизирована или вы натолкнулись на ошибку в библиотеке Си в вашей системе. (Такое случалось!) Ваша копия может получить фатальный сбой, а наша может не получить. Если вы скажете, что ожидается крах, тогда, если наш Emacs не получит фатальный сбой, мы узнали бы, что ошибки не происходит. Если бы вы не сказали, то мы не узнали бы, происходит ли ошибка, -- мы не смогли бы сделать никаких выводов из наших наблюдений.
  • Если проявление неполадки -- это сообщение Emacs об ошибке, то важно описать точный текст сообщения и след, показывающий, каким образом Лисп-программа в Emacs пришла к ошибке. Чтобы точно получить текст сообщения об ошибке, скопируйте его из буфера `*Messages*' в ваш отчет. Скопируйте его полностью, а не только часть. Чтобы получить след для ошибки, выполните лисповское выражение (setq debug-on-error t) перед тем, как произойдет ошибка (то есть вы должны выполнить это выражение, а потом повторить ситуацию, приводящую к ошибке). При возникновении ошибки это вызывает запуск отладчика Лиспа, который покажет вам след. Скопируйте текст следа отладчика в описание ошибки. Такое использование отладчика возможно только в том случае, если вы знаете, как вызвать ошибку снова. Если вы не можете воспроизвести её, по крайней мере скопируйте полное сообщение об ошибке.
  • Проверьте все программы, которые вы загрузили в среду Лиспа, включая ваш файл `.emacs', не устанавливают ли они какие-либо переменные, которые могут влиять на функционирование Emacs. Также посмотрите, случается ли ошибка в только что запущенном Emacs без загрузки файла `.emacs' (запустите Emacs с ключом -q, это предотвратит загрузку файла инициализации). Если в этом случае ошибка не встретится, вы должны сообщить точное содержание всех программ, которые вы должны загрузить в среду Лиспа для того, чтобы заставить ошибку проявиться.
  • Если оказалось, что ошибка зависит от файла инициализации или других Лисп-программ, которые не являются частью стандартной системы Emacs, тогда вы должны удостовериться, что это не ошибка этих программ, обращаясь сперва к тем, кто их сопровождает. После того, как они подтвердят, что используют Emacs так, как ими предполагалось, они должны сообщить об этой ошибке.
  • Если вы хотите сослаться на какое-то место в исходном тексте GNU Emacs, покажите эту строку кода и несколько строк контекста. Не давайте только номер строки. Номера строк в рабочих исходных текстах не совпадают с номерами в ваших файлах. Выяснение того, какой код находится в указанной строке в вашей версии, создаст дополнительную работу сопроводителям, и мы не сможем быть точно уверены.
  • Дополнительная информация из отладчика Си, такого как GDB, может позволить нам найти проблему, возникающую на машине, которая нам недоступна. Если вы не умеете пользоваться GDB, пожалуйста, прочитайте руководство по нему -- оно не слишком длинное, а GDB прост в применении. Вы можете найти дистрибутив GDB с интерактивным руководством в большинстве тех же мест, где вы можете получить дистрибутив Emacs. Чтобы запустить Emacs под GDB, вам нужно перейти в подкаталог `src', в котором был скомпилирован Emacs, и выполнить `gdb emacs'. Важно, чтобы каталог `src' был текущим, чтобы GDB считал в нем файл `.gdbinit'. Однако, при сборе дополнительных сведений вам придется подумать, если вы хотите, чтобы они показали, что же именно вызывает ошибку. Например, многие посылают только след, но сам по себе он не очень полезен. Простой след с аргументами зачастую мало говорит о том, что происходит внутри GNU Emacs, потому что большинство перечисленных в нем аргументов являются указателями на лисповские объекты. Численные значения этих указателей не имеют никакой значимости; все, что играет роль -- это содержимое объектов, на которые они указывают (и большая часть их содержимого -- тоже указатели). Чтобы предоставить полезную информацию, вам нужно показать значения лисповских объектов в лисповской записи. Сделайте это для каждой переменной, являющейся лисповским объектом, в нескольких нижних фреймах стека. Посмотрите в исходный текст, чтобы узнать, какие переменные являются лисповскими объектами, потому что отладчик считает их целыми числами. Чтобы показать значение переменной в лисповской записи, сначала напечатайте её значение, а потом используйте определённую пользователем команду GDB pr, которая напечатает лисповский объект в синтаксисе Лиспа. (Если вам приходится использовать другой отладчик, вызовите функцию debug_print с этим объектом в качестве аргумента.) Команда pr определена в файле `.gdbinit' и работает, только если вы отлаживаете запущенный процесс (не дамп памяти). Чтобы ошибка в Лиспе останавливала Emacs и возвращала в GDB, установите контрольную точку в Fsignal. Чтобы выяснить с помощью GDB, какие лисповские функции сейчас выполняются, переходите вверх по стеку и каждый раз, когда вы попадаете во фрейм функции Ffuncall, пишите следующие команды GDB:
    p *args
    pr
    
    Чтобы напечатать первый аргумент, полученный этой функцией, используйте эти команды:
    p args[1]
    pr
    
    Другие аргументы вы можете напечатать подобным же образом. Аргумент nargs функции Ffuncall говорит, сколько аргументов получила Ffuncall; это включает саму лисповскую функцию и её аргументы. Файл `.gdbinit' определяет другие команды, полезные для просмотра типов и содержимого лисповских объектов. Их имена начинаются с `x'. Эти команды работают на более низком уровне, чем pr, и менее удобны, но они могут работать, даже когда pr не работает, например при отладке дампа памяти, или когда Emacs получил фатальный сигнал.
  • Если симптом ошибки состоит в том, что Emacs не отвечает, не предполагайте, что он "завис" -- он может быть в бесконечном цикле. Чтобы выяснить, что же именно происходит, воспроизведите проблему под GDB и остановите Emacs, когда он не отвечает. (Если Emacs непосредственно использует X Windows, вы можете его остановить, набрав в GDB команду C-z.) Затем попробуйте выполнить один шаг с помощью `step'. Если Emacs завис, команда `step' не вернется. Если Emacs зациклился, `step' вернется. Если это покажет, что Emacs завис на системном вызове, остановите его снова и проверьте аргументы этого вызова. В вашем отчете укажите точно, где в исходном тексте находится этот системный вызов, и каковы его аргументы. Если Emacs попал в бесконечный цикл, пожалуйста, определите, где этот цикл начинается и где завершается. Простейший способ сделать это --- использовать команду GDB `finish'. При каждом её использовании Emacs продолжает выполнение, пока не выйдет из одного фрейма стека. Продолжайте набирать `finish', пока она не перестанет возвращаться --- это будет означать, что бесконечный цикл находится в том фрейме стека, который вы только что пытались завершить. Остановите Emacs снова и вводите последовательно `finish', пока вы не вернетесь в тот же фрейм. Тогда используйте `next', чтобы пройти сквозь этот фрейм. С помощью пошагового выполнения вы увидите, где цикл начинается и где заканчивается. Также, пожалуйста, проверьте используемые в цикле данные и попытайтесь выяснить, почему цикл не завершается, когда нужно. Включите все эти сведения в ваш отчет об ошибке.

Вот некоторые вещи, которые необязательны в отчете об ошибке:

  • Исчерпывающее описание условий возникновения и не возникновения ошибки --- это не нужно для воспроизводимых ошибок. Нередко люди, сталкивающиеся с ошибкой, тратят много времени на выяснение того, какие изменения во входном файле заставят ошибку исчезнуть, а какие не затронут её. Это зачастую требует много времени и не столь полезно, потому что мы будем искать ошибку, запуская один пример в отладчике с контрольными точками, а не чистой дедукцией из серии примеров. Вы также можете сэкономить время, не выискивая дополнительные примеры. Разумеется, если вы можете найти более простой пример для сообщения вместо изначального, это будет удобнее. Ошибки в выводе будет легче обнаружить, работа в отладчике займет меньше времени, и так далее. Однако, упрощение не жизненно важно; если вы не можете это сделать, или у вас нет времени пытаться, пожалуйста, сообщите об ошибке с первоначальным тестовым примером.
  • След системных вызовов работы Emacs. Следы системных вызовов очень полезны для некоторых особых видов отладки, но чаще всего они дают мало полезной информации. Поэтому странно, что многие, как кажется, считают, что именно оправка следа системных вызовов -- это и есть отчет об фатальном сбое. Возможно, эта привычка сформировалась из опыта отладки программ, к которым нет исходного текста, или в которых нет отладочных символов. В большинстве программ след вызовов подпрограмм гораздо, гораздо информативнее следа системных вызовов. Даже в Emacs простой след подпрограмм обычно более информативен, хотя чтобы дать все сведения, вы должны дополнить след, показав значения переменных и напечатав их как лисповские объекты с помощью pr (смотрите выше).
  • Заплата для ошибки. Заплата для ошибки полезна, если это хорошая заплата. Но не опускайте в отчете об ошибке другую необходимую информацию, такую как тестовый пример, в предположении, что заплаты достаточно. Мы можем увидеть недочеты в вашей заплате и решить проблему другим способом или не понять её совсем. И если мы не можем понять, какую ошибку предполагает исправить ваша заплата, или почему она должна быть улучшением, мы не должны её устанавливать.
  • Предположения о том, чем является эта ошибка, или от чего она зависит. Такие предположения обычно неверны. Даже эксперты не могут правильно догадываться о таких вещах, не применив сначала отладчик для выяснения фактов.

Отправка заплат для GNU Emacs

Если хотите написать исправления ошибок или улучшения для GNU Emacs, это очень нам поможет. Когда вы посылаете ваши изменения, пожалуйста, следуйте этим рекомендациям, чтобы сопроводителям было легче их использовать. Если вы не следуете им, ваши изменения тем не менее могут быть полезны, но использование их потребует дополнительной работы. Сопровождение GNU Emacs -- это в лучших обстоятельствах много работы, и нам будет трудно справляться, если вы не сделаете все от вас зависящее, чтобы нам помочь.

  • Посылайте вместе с вашими изменениями объяснение, какую проблему они решают, или какое улучшение они приносят. Для исправления ошибки просто включите описание этой ошибки и объясните, как это изменение её исправляет. (Ссылка на сообщение об ошибке не так хороша, как включение самого сообщения, потому что тогда нам придётся искать, и возможно, мы его уже удалили, если ошибка уже исправлена.)
  • Всегда включайте хорошее описание проблемы, которую, как вы думаете, вы решили. Мы должны убедиться, что изменение правильно, перед тем как его устанавливать. Даже если оно правильно, у нас могут быть трудности с его пониманием, если сами мы не можем воспроизвести эту ошибку.
  • Включайте все необходимые комментарии, которые в будущем помогут понять цель этого изменения другим людям, читающим исходный текст.
  • Не перемешивайте изменения, сделанные по разным причинам. Посылайте их раздельно. Если вы делаете два изменения по разным причинам, мы можем не захотеть устанавливать их оба. Возможно, мы решим установить только одно. Если вы пошлете их перемешанными в одном наборе заплат, мы должны будем делать дополнительную работу, чтобы их распутать -- чтобы понять, какие части изменения служат каким целям. Если у нас нет на это времени, мы можем проигнорировать ваши изменения целиком. Если вы посылаете каждое изменение, как только вы его написали, с отдельным объяснением, то два этих изменения не перепутаются, и мы сможем подробно рассмотреть каждое, не затрачивая дополнительных усилий на их разделение.
  • Посылайте каждое изменение, как только вы его закончили. Иногда люди считают, что помогают нам, накапливая много изменений и посылая их все вместе. Как объяснено выше, это наихудшее, что вы можете сделать. Поскольку вы должны посылать каждое изменение отдельно, вы также могли бы посылать их немедленно. Это даст нам возможность установить ваше изменение сразу же, если это важно.
  • Для создания заплат используйте `diff -c'. Заплаты без контекста трудно установить надежно. Более того, их трудно изучать; мы должны всегда изучать заплату, чтобы решить, нужно ли её устанавливать. Объединенный формат лучше бесконтекстного, но его не так легко читать, как формат `-c'. Если у вас есть GNU diff, используйте при создании заплат в коде на Си команду `diff -c -F'^[_a-zA-Z0-9$]+ *(''. Это покажет каждое имя функции, в которой находится изменение.
  • Избегайте любой неоднозначности в том, что является старой версией, а что новой. Пожалуйста, задавайте старую версию первым аргументом diff, а новую версию вторым. И пожалуйста, давайте той или иной версии такое имя, которое показывало бы, старый это файл или ваш измененный.
  • Пишите для ваших изменений журнальные записи. Это избавит нас от дополнительной работы по их написанию и поможет разъяснить ваши изменения, чтобы мы могли их понять. Цель журнала изменений -- показать людям, где искать измененные места. Поэтому вы должны точно указывать, какие функции вы изменили; в больших функциях также часто полезно указывать, где именно в этой функции было сделано изменение. С другой стороны, когда вы показали людям, где найти изменение, вам не нужно объяснять его цель в журнале изменений. Таким образом, если вы добавили новую функцию, все, что вы должны сказать, -- это что она новая. Если вы чувствуете, что цель этого требует разъяснения, то это, скорее всего, так и есть, но помещайте разъяснение в комментариях в коде. Там оно будет более полезно. Пожалуйста, прочитайте файлы `ChangeLog' в каталогах `src' и `lisp', чтобы понять, какого сорта сведения в них нужно писать, и освоить используемый нами стиль. Если вы хотите, чтобы в строке заголовка, показывающей автора изменения, появилось ваше имя, пошлите нам этот заголовок. Смотрите раздел Журналы изменений.
  • Когда вы пишете исправление, помните, что мы не можем установить изменение, которое могло бы нарушить работу на других системах. Пожалуйста, подумайте об эффекте, который может иметь ваше изменение, если его скомпилировать на системе другого типа. Иногда люди присылают исправления, которые могут быть улучшением в общем -- но убедиться в этом трудно. Установить такие изменения трудно, потому что мы должны изучить их очень внимательно. Конечно, хорошее пояснение рассуждений, благодаря которым вы пришли к осознанию правильности такого изменения, может помочь убедить нас. Самые безопасные изменения -- это изменения в конфигурационных файлах для конкретной машины. Они безопасны, потому что не могут повлечь за собой новых ошибок на других машинах. Пожалуйста, помогите нам справляться с нагрузкой, разрабатывая заплату таким образом, чтобы было ясно, что её установка безопасна.

Содействие в разработке Emacs

Если вы хотели бы помочь в тестировании выпусков Emacs, чтобы убедиться, что они работают правильно, или если вы хотели бы работать над улучшением Emacs, пожалуйста, свяжитесь с сопроводителями по адресу bug-gnu-emacs@gnu.org. Испытатель должен быть готов как к исследованию ошибок, так и к их описанию. Если вы желаете улучшить Emacs, пожалуйста, спросите о предлагающихся проектах или предложите свои идеи.

Если вы уже написали расширение, пожалуйста, сообщите нам об этом. Если вы ещё не начали работу, будет полезным связаться с bug-gnu-emacs@gnu.org до того, как вы начнете; тогда мы сможем посоветовать, как сделать так, чтобы ваши расширения лучше стыковались с остальной частью Emacs.

Как получить помощь по GNU Emacs

Если вы нуждаетесь в помощи по установке, использованию или модификации GNU Emacs, у вас есть два способа получить её:

  • Послать сообщение в список рассылки help-gnu-emacs@gnu.org или опубликовать ваш запрос с группе новостей gnu.emacs.help. (Этот список рассылки и группа новостей сообщаются между собой, поэтому безразлично, что именно вы будете использовать.)
  • Посмотреть в каталоге услуг, нет ли кого-нибудь, кто сможет вам помочь за плату. Этот каталог находится в файле с именем `etc/SERVICE' в дистрибутиве Emacs.

Назад |  Вперед |  Содержание



Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения.
Идея и реализация: © Владимир Довыденков и Анатолий Камынин,  2004-2024