Решение  частых проблем – ЧАСТЬ 3

сти предложение, подобное предыдущему,  так как это дает все факты.

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

вероятно, без ‘z’  в его имени и не нашли бы никакой ошибки.  Мы никак не могли бы догадаться, что должны были попробовать обратиться к файлу с буквой ‘z’ в имени.

С другой стороны, ошибка могла возникнуть из-за того, что файл начинается  точно с

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

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

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

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

Лучший способ сообщить об ошибке — отправить электронное письмо сопроводителям 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.   Она подготавливает буфер сообщения  (см.   Глава 26 [Посылка почты], с. 267) и автоматически вставляет некоторую важную информацию. Однако, она не может предоставить всю необходимую информацию; вы все равно должны прочитать приведенные ниже рекомендации и следовать им, тогда вы можете ввести остальные нужные сведения вручную перед отправкой сообщения.

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

дующие сведения:

Номер версии Emacs.  Без этого мы не  сможем узнать, есть ли смысл искать  эту ошибку в текущей версии GNU Emacs.

Вы можете получить номер версии, набрав M-x emacs-version hRETi. Если эта команда не работает, то у вас, вероятно, стоит не GNU Emacs, а что-то другое, поэтому вам лучше сообщать об ошибке по другому адресу.

Тип используемой вами машины и название и номер версии операционной системы.

M-x emacs-version hRETi  предоставляет также и эту информацию.  Скопируйте ее вы-

вод из буфера ‘*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 получает фатальный сигнал” или “Получается вот такой текст, что, как я думаю, неправильно”.2

2  Писать отчеты нужно, конечно, на английском. Если вы не знаете английского сами, найдите того, кто вам поможет. (Прим. переводчика)

Конечно, если ошибка проявляется в том, что Emacs получает фатальный сигнал, ее нельзя не заметить. Но если ошибка — это неправильный текст, сопроводитель может не заметить, где же тут проблема. Зачем оставлять такую возможность?

Даже если проблема в том, что возникает фатальный сигнал, вы тем не менее должны сказать это явно. Предположим, произошло что-то странное, например, ваша копия исходного текста не синхронизирована  или вы натолкнулись на ошибку в библиотеке Си в вашей системе. (Такое случалось!) Ваша копия может получить фатальный сбой, а наша может не получить. Если вы скажете, что ожидается крах, тогда, если наш Emacs не получит фатальный сбой, мы узнали бы, что ошибки не происходит. Если бы вы не сказали, то мы не узнали бы, происходит ли ошибка, — мы не смогли бы сделать никаких выводов из наших наблюдений.

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

Чтобы  точно  получить  текст  сообщения об ошибке,   скопируйте   его  из  буфера

‘*Messages*’ в ваш отчет. Скопируйте его полностью, а не только часть.

Чтобы получить след  для ошибки, выполните  лисповское выражение (setq debugon-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 xbacktrace.

Если вы хотите  исследовать  аргументы лисповских функций, переходите  вверх по стеку и каждый  раз, когда попадаете  во фрейм  функции 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 (смотрите выше).

Заплата для ошибки.

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

Предположения о том, чем является эта ошибка, или от чего она зависит.

Такие предположения обычно неверны. Даже эксперты не могут правильно догады-

ваться о таких вещах, не применив сначала отладчик для выяснения фактов.

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

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

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

Посылайте вместе с вашими изменениями  объяснение, какую проблему они решают, или какое улучшение они приносят. Для исправления ошибки просто включите описание этой ошибки и объясните, как это изменение  ее исправляет.

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

Всегда включайте хорошее описание проблемы, которую, как вы думаете, вы решили.

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

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

Не перемешивайте  изменения,  сделанные по разным причинам.  Посылайте  их раз

дельно.

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

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

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

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

Для создания заплат используйте ‘diff -c’.  Заплаты без контекста трудно установить надежно.  Более того, их трудно изучать; мы должны всегда изучать заплату, чтобы решить, нужно ли ее устанавливать. Объединенный формат лучше бесконтекстного, но его не так легко читать, как формат ‘-c’.

Если у вас есть GNU diff, используйте при создании заплат в коде на Си команду ‘diff

-c -F’^[_a-zA-Z0-9$]+ *(’’.  Это покажет каждое имя функции, в которой находится изменение.

Избегайте  любой неоднозначности в том, что является старой версией, а что новой.

Пожалуйста, задавайте старую версию первым аргументом diff, а новую версию вторым. И пожалуйста, давайте той или иной версии такое имя, которое показывало бы, старый это файл или ваш измененный.

Пишите для ваших изменений журнальные записи. Это избавит нас от дополнительной работы по их написанию и поможет разъяснить ваши изменения, чтобы мы могли их понять.

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

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

Пожалуйста, прочитайте файлы ‘ChangeLog’ в каталогах ‘src’  и ‘lisp’, чтобы понять, какого сорта сведения в них нужно писать, и освоить используемый нами стиль. Если вы хотите,  чтобы в строке  заголовка, показывающей автора изменения, появилось ваше имя, пошлите нам этот заголовок. См. Раздел 22.12 [Change Log], с. 224.

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

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

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

Пожалуйста, помогите  нам справляться с нагрузкой, разрабатывая  заплату таким образом, чтобы было ясно, что ее установка безопасна.

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

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

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

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

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

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

Посмотреть в каталоге услуг, нет ли кого-нибудь, кто сможет вам помочь за плату.

Этот каталог находится в файле с именем ‘etc/SERVICE’ в дистрибутиве Emacs.

Источник: Ричард Столмен, Руководство по GNU Emacs

Похожие посты:

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий