Когда вы используете выражение «@» для отключения сообщений об ошибках PHP, а не просто отладки проблемы? [Дубликат]

Это означает, что ваш код использовал ссылочную переменную объекта, которая была установлена ​​в нуль (т. е. она не ссылалась на экземпляр фактического объекта).

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

if (myvar != null)
{
    // Go ahead and use myvar
    myvar.property = ...
}
else
{
    // Whoops! myvar is null and cannot be used without first
    // assigning it to an instance reference
    // Attempting to use myvar here will result in NullReferenceException
}
62
задан VolkerK 27 April 2010 в 00:17
поделиться

14 ответов

Я бы подавил ошибку и обработал ее. В противном случае у вас может быть проблема с TOCTOU (время проверки, время использования. Например, файл может быть удален после того, как file_exists вернет true, но до fopen).

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

24
ответ дан Paweł Hajdan 25 August 2018 в 13:38
поделиться
  • 1
    Проблема в том, что вы в конечном итоге подавляете другие ошибки, которые вы не прогнозировали, а затем тратите весь свой день на поиск ошибки, которая не вызывает ошибок. В редкой ситуации с проблемой TOCTOU я считаю, что гораздо лучше ошибиться, поскольку ошибки PHP не должны отображаться конечным пользователям в любом случае, но это все равно позволит кому-то быть в курсе ситуации путем регистрации ошибок или их отображения если скрипт запущен в среде разработки. Ошибка при подавлении ошибок - лучший способ скрыть проблему. (например, удаляемые файлы :)) – Gerry 6 June 2009 в 18:09
  • 2
    Это прекрасно, но для любви к тому, чтобы вас не преследовали и не убивали, проверьте правильную ошибку. Я однажды слишком долго отслеживал проблему с базой данных - я видел ошибки Close (), и ничего не работало. В конце концов я обнаружил, что гениальное @ 'd исходное соединение и "else" проверка была практически пустой. Удалив @, я сразу смог распознать, что учетные данные подключения были плохими. – anonymous coward 11 June 2009 в 17:23

Вы не хотите подавлять все, так как это замедляет ваш скрипт.

И да, есть способ как в php.ini, так и внутри вашего скрипта удалить ошибки (но делать это только тогда, когда вы находятся в живой среде и записывают ваши ошибки из php)

<?php
    error_reporting(0);
?>

И вы можете прочитать это для версии php.ini, отключив ее.

1
ответ дан Ólafur Waage 25 August 2018 в 13:38
поделиться
  • 1
    Я не ищу способ отключить его, я ищу, есть ли причина для его использования, как во всем, что невозможно обработать без использования @ (один элемент до сих пор - mysql_connect) – Mez 26 September 2008 в 02:14
  • 2
    Здравствуй! Что мешает сценарию? благодаря! – Industrial 23 May 2010 в 19:46
  • 3
    @Industrial делает дополнительную работу, подавляющую ошибки. Так как он должен отображать ошибку, но находит @ там и имеет дело с ней динамически. – Ólafur Waage 23 May 2010 в 20:04
  • 4
    Ах! Поэтому было бы лучше следовать вашему примеру - error_reporting (0) ;? – Industrial 23 May 2010 в 20:35
  • 5
    @Industrial Если вы регистрируете ошибки в другом месте, да. – Ólafur Waage 23 May 2010 в 21:17

Если вы используете пользовательскую функцию обработки ошибок и хотите подавить ошибку (возможно, известную ошибку), используйте этот метод. Использование «@» не является хорошей идеей в этом контексте, поскольку оно не будет подавлять ошибку, если установлен обработчик ошибок.

Напишите 3 функции и вызовите это.

# supress error for this statement
supress_error_start();  
$mail_sent = mail($EmailTo, $Subject, $message,$headers);
supress_error_end(); #Don't forgot to call this to restore error.  

function supress_error_start(){
    set_error_handler('nothing');
    error_reporting(0);
}

function supress_error_end(){
    set_error_handler('my_err_handler');
    error_reporting('Set this to a value of your choice');
}

function nothing(){ #Empty function
}

function my_err_handler('arguments will come here'){
      //Your own error handling routines will come here
}
0
ответ дан 2 revs, 2 users 88% 25 August 2018 в 13:38
поделиться

Я НИКОГДА не позволяю себе использовать «@» ... период.

Когда я обнаруживаю использование «@» в коде, я добавляю комментарии, чтобы сделать его очевидным, как в момент использования , и в док-блоке вокруг функции, в которой он используется. Я тоже был укушен отладкой «преследовать призрак» из-за такого подавления ошибок, и я надеюсь облегчить его следующее, выделив его использование, когда я его найду.

В тех случаях, когда Я хочу, чтобы мой собственный код выдавал исключение, если встроенная функция PHP обнаруживает ошибку, а «@» - это простой способ, я вместо этого хочу сделать что-то другое, получающее тот же результат, но (снова) явственно видно в коде:

$orig = error_reporting(); // capture original error level
error_reporting(0);        // suppress all errors
$result = native_func();   // native_func() is expected to return FALSE when it errors
error_reporting($orig);    // restore error reporting to its original level
if (false === $result) { throw new Exception('native_func() failed'); }

Это намного больше кода, который просто пишет:

$result = @native_func();

, но я предпочитаю, чтобы мое подавление требовало ОЧЕНЬ ОБЫЧНОГО, ради бедная отладочная душа, которая следует за мной.

6
ответ дан ashnazg 25 August 2018 в 13:38
поделиться
  • 1
    Это мнение и не очень хорошее. Вы можете выполнить одно и то же: $ result = @native_func (); и если ($ result) без этого уродливого беспорядка. Я согласен, что это плохо, но только если его не обрабатывают. – Mfoo 12 March 2015 в 11:30
  • 2
    Как вы думаете, он более кошерный, чем @fopen? Вы также отключите отчет об ошибках, но с большим количеством кода и большим временем выполнения. IIRC try ... catch не будет работать из-за того, что это предупреждение не ошибка ... try ... catch в этом случае будет одним кошерным решением. Он скрывает только предупреждение NetBeans ... – 18C 9 December 2017 в 04:10
  • 3
    Проблема, которую я пытаюсь решить здесь, заключается в том, чтобы показать следующему разработчику, что подавление происходит. Я хочу пожертвовать строками кода, микро-оптимизированным временем выполнения и предполагаемым уродством для достижения моей цели. Я не вижу «наилучшего способа». который охватывает все потребности, поэтому я выбираю свои компромиссы. – ashnazg 9 December 2017 в 15:34

Если вы не хотите вызывать предупреждение при использовании таких функций, как fopen (), вы можете подавить ошибку, но использовать исключения:

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}
11
ответ дан dirtside 25 August 2018 в 13:38
поделиться
  • 1
    Это мой предпочтительный метод – MattBelanger 11 June 2009 в 17:21
  • 2
    Если вы выбрасываете исключение, вам не нужно строго else, просто do_file_stuff(). – MrWhite 21 January 2014 в 18:08

Одно место, которое я использую, это код сокета, например, если у вас установлен тайм-аут, вы получите предупреждение об этом, если вы не включите @, даже если оно действительно не для получения пакета.

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port )
2
ответ дан Don Neufeld 25 August 2018 в 13:38
поделиться

нет способа подавить предупреждения и ошибки php.ini? в этом случае вы можете отлаживать только изменение флага и не пытаться обнаружить, что @ скрывает проблему.

3
ответ дан Enrico Murru 25 August 2018 в 13:38
поделиться
  • 1
    да, вы можете сделать error_reporting (E_ALL & amp; ~ E_NOTICE & amp; ~ E_WARNING) - но я не хочу этого делать, см. отредактированный вопрос – Mez 26 September 2008 в 02:17

Использование @ иногда является результативным. По моему опыту, вы всегда должны отключать отчет об ошибках в php.ini или вызывать

error_reporting(0);

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

3
ответ дан Eric Lamb 25 August 2018 в 13:38
поделиться
  • 1
    Я предпочитаю, чтобы ошибки были видимыми. То, что я пытаюсь решить, если есть какой-либо способ, которым вам придется использовать @, или у вас может быть ошибка, которую нельзя поймать раньше. – Mez 26 September 2008 в 02:07
  • 2
    Я никогда не видел экземпляр, где использование @ для подавления ошибок было положительным. Он скрывает все будущие ошибки, а не только тот, который вы хотели игнорировать. – Gerry 6 June 2009 в 17:50
  • 3
    Не выключайте error_reporting, это безумие! Пока вы снова включаете его, убедитесь, что он способен регистрировать ошибки в файле, который вы можете прочитать позже. Правильный способ не показывать ошибки пользователям через ini_set('display_errors',0); или еще лучше, напрямую изменить INI-файл, чтобы включить это. – Chinoto Vokro 26 February 2016 в 18:41

Примечание: во-первых, я понимаю, что 99% разработчиков PHP используют оператор подавления ошибок (я был одним из них), поэтому я ожидаю, что любой PHP-разработчик увидит, что это не согласуется.

Как вы считаете, действительно ли действительно использовать оператор @ для подавления ошибки / предупреждения в PHP, тогда как вы можете обрабатывать ошибку?

Краткий ответ: Нет!

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

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

Проблема в том, что кусок кода, с которым вы подавляете ошибки, в настоящее время может вызывать только ошибку, которую вы видите; однако, когда вы меняете код, на который полагается подавленная линия, или среда, в которой она выполняется, тогда есть все шансы, что линия попытается вывести совершенно другую ошибку из той, которую вы пытались игнорировать. Тогда как вы отслеживаете ошибку, которая не выводится? Добро пожаловать в отладку ада!

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

Альтернативы (в зависимости от ситуации и желаемого результата): обрабатывайте фактическую ошибку, о которой вы знаете, так что, если часть кода вызовет определенную ошибку, тогда он не будет запущен в этой конкретной ситуации. Но я думаю, что вы получаете эту часть, и вы просто беспокоились о том, что конечные пользователи видят ошибки, и это то, что я сейчас адресую.

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

Для фатальных ошибок установите display_errors в выключенном состоянии (ваш обработчик ошибок все еще получает ) в вашем php.ini и включить ведение журнала ошибок. Если у вас есть сервер разработки, а также живой сервер (который я рекомендую), этот шаг не требуется на вашем сервере разработки, поэтому вы можете отлаживать эти фатальные ошибки, не прибегая к просмотру файла журнала ошибок. Существует даже трюк , использующий функцию выключения , чтобы отправить большое количество фатальных ошибок вашему обработчику ошибок.

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

Вы можете прочитать мой комментарий к странице «Операторы контроля ошибок» в руководстве по PHP, если вы хотите получить дополнительную информацию.

112
ответ дан halfer 25 August 2018 в 13:38
поделиться
  • 1
    Это абсолютно правильно. Подавление ошибок является фундаментальной ошибкой. Используйте обработчик ошибок или используйте исключения, не скрывайте ошибку. – MattBelanger 11 June 2009 в 17:20
  • 2
    -1 для поглаживания глупых "является злым" мем. Исключение встроенной языковой функции с явным пренебрежением к фактическому варианту использования - это основное определение программирования культовых грузов. - В частности, в этом заявлении не упоминается, что подавленные ошибки фактически не исчезли. Пользовательский обработчик ошибок может все еще оживить их (set_error_handler("var_dump"); - ленивый эквивалент расширения крика). Более того, такие чрезмерные советы приводят к обычным обходным синтаксическим синтаксическим искажениям isset(), которые фактически могут препятствовать отладке (поскольку отладочные уведомления затем подавляются безвозвратно). – mario 24 October 2011 в 15:57
  • 3
    @mario "с явным игнорированием фактического варианта использования" ... хмммм .. Возможно, вы не читали полный текст "is evil". «Возможно, для этого есть веская причина, но я еще не видел этого, поэтому до сих пор я считаю, что оператор (@) подавления ошибок является« злым ». Я говорил, что еще не нашел такой контекст. Похоже, у вас есть ответ на вопрос, который спросил Оп, возможно, вы могли бы рассмотреть вопрос о том, где будет больше места для обсуждения ваших взглядов. – Gerry 26 October 2011 в 16:06
  • 4
    Ваш код не проверяет индекс, прежде чем проверять его значение. Это приведет к затруднению отслеживания проблем, скажем, если элемент формы переименован или запутан. Необязательный индекс означает что-то другое, что элемент формы остается пустым. Также вы не должны показывать ошибки конечным пользователям. Если у вас просто проблемы с HTML / JSON в разработке и вы думаете, что это нормально, чтобы оставить их, мы тут не согласны. Замечания о типичном пути выполнения обычно указывают на неспособность обрабатывать условия, которые вы должны обрабатывать. – Gerry 23 April 2012 в 22:41
  • 5
    @Gerry: Ты был прав. Надежда, которая помогает другим: имеет @ в заявлении include, и когда приложение будет разбиваться время от времени, ничто не будет регистрироваться в журнале ошибок php. Причина в том, что @ в include включает в себя MUCH больше, чем если он был включен успешно или нет, только, но также применяется к функциям, исходящим из подавленного «include», они НЕ будут регистрировать ошибки, когда вы их позднее назовете. Больше не включено для меня. – Wadih M. 16 February 2017 в 03:13

Да, подавление имеет смысл.

Например, команда fopen() возвращает FALSE, если файл не может быть открыт. Это нормально, но также создает предупреждающее сообщение PHP. Часто вы не хотите предупреждения - вы сами проверите FALSE.

На самом деле руководство по PHP специально предлагает использовать @ в этом случае!

19
ответ дан Jason Cohen 25 August 2018 в 13:38
поделиться
  • 1
    но, конечно, этого можно избежать, сначала проверив файл file_exists ($ file)? – Mez 26 September 2008 в 02:03
  • 2
    Нет, он не может, существуют другие условия отказа, такие как «нет разрешений на чтение». или "файл занят". – Jason Cohen 26 September 2008 в 02:46
  • 3
    Это здорово, пока fopen не выдает ошибку, которую вы не ожидали. Вы не можете проверить все свои известные условия ошибки? Создайте функцию обертки fopen. – Gerry 28 January 2012 в 06:49
  • 4
    Я был искушен, чтобы плюнуть на тебя, только потому, что ты Джейсон Коэн. Отличный ответ / комментарий. – Marco Demaio 22 February 2013 в 16:57
  • 5
    @JasonCohen Что относительно secure.php.net/is_readable ? Тем не менее, есть еще условие гонки ... – John M. 4 November 2015 в 00:50

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

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

То, что вам действительно нужно, это полагаться на «error_log» php, чтобы быть вашим методом отчетности, так как вы не можете полагаться на просмотр пользователями страниц, чтобы сообщать об ошибках. (И вы также должны отключить php от отображения этих ошибок)

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

Если вы действительно должны обрабатывать ошибки, вы можете создать собственный обработчик ошибок

http://php.net/set-error-handler

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

6
ответ дан Kent Fredric 25 August 2018 в 13:38
поделиться
  • 1
    Я знаю, что я не должен недооценивать ошибки, но некоторые вещи будут генерировать E_WARNING или E_NOTICE, когда не нужно фактически показывать это конечному пользователю, и во многих случаях этого можно избежать, чтобы фактически их использовать. кроме, на данный момент в случае mysql_open – Mez 26 September 2008 в 02:16
  • 2
    @martin meredith: вот почему вы используете & quot; error_log & quot; и & quot; display_errors = false & quot; – Kent Fredric 26 September 2008 в 07:35
  • 3
    @Kent - Лучший ответ на этой странице! [edit: сделай это вторым, потому что я только что добавил один: P] @Mez - Как предложил Кент, настройте обработчик ошибок, который отображает ошибки только вам. – Gerry 6 June 2009 в 19:53

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

$script_ok = @eval('return true; '.$script);

AFAIK, это самый элегантный способ сделать это.

3
ответ дан Milan Babuškov 25 August 2018 в 13:38
поделиться
  • 1
    Во-первых, eval () никогда не должен использоваться. Во-вторых, если $ script содержит функции, они будут оцениваться, а затем во второй раз это будет запущено, он будет жаловаться, что эти функции уже определены и завершены. – Chinoto Vokro 26 February 2016 в 18:46

Я использую его при попытке загрузить HTML-файл для обработки в качестве объекта DOMDocument. Если в HTML есть какие-либо проблемы ... и на каком веб-сайте нет хотя бы один ... DOMDocument-> loadHTMLFile () выдает ошибку, если вы не подавите ее с помощью @ , Это единственный способ (возможно, лучшие). Мне когда-либо удавалось создавать HTML-скребки в PHP.

-1
ответ дан Steve Paulo 25 August 2018 в 13:38
поделиться

Большинство людей не понимают значения сообщения об ошибке. Без шуток. Большинство из них.

Они считают, что сообщения об ошибках одинаковы, говорит: «Что-то не так!» Они не удосужились его прочитать. Хотя это самая важная часть сообщения об ошибке, а не только тот факт, что она была поднята, но это имеет значение. Это может сказать вам , что идет не так. Сообщения об ошибках предназначены для помощи, а не для того, чтобы беспокоить вас «как скрыть это?». проблема. Это одно из самых больших недоразумений в мире веб-программирования новичка.

Таким образом, вместо сообщения об ошибке gagging следует прочитать то, что он говорит. Он имеет не только одно значение «файл не найден». Могут быть тысячи разных ошибок: permission denied, save mode restriction, open_basedir restriction и т. Д. Каждый из них требует соответствующих действий. Но если вы заткнете это, вы никогда не узнаете, что произошло!

OP представляет собой сообщение об ошибках с обработкой ошибок, в то время как это очень большая разница! Обработка ошибок для пользователя. «что-то случилось» достаточно. Хотя сообщения об ошибках предназначены для программистов, которым отчаянно нужно знать, что именно произошло.

Таким образом, сообщения о ошибках никогда не появляются. Оба регистрируют его для программиста и обрабатывают его для пользователя.

5
ответ дан Your Common Sense 25 August 2018 в 13:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: