【问题标题】:The message for class "Exception" causes PHP Fatal Error类“异常”的消息导致 PHP 致命错误
【发布时间】:2019-02-07 23:42:37
【问题描述】:

执行此简单代码后:

$message = 'some text '.inet_pton('119.252.33.171');
throw new \Exception($message);

PHP 返回致命错误

Fatal error</b>: in ...

此代码预计会返回

Fatal error: Uncaught Exception: ..

但这并没有发生。使用此消息,错误发生在“异常”类中!

Code example 1 from sandbox.onlinephpfunctions.com(注释和取消注释 2 行代码 3-4 和 6-7)

Code example 2 from sandbox.onlinephpfunctions.com

在转换许多其他 IP 时会注意到此行为。 目前,我在“throw new”之前使用以下行解决了问题:

$message = preg_replace( '/[^[:print:]\r\n]/', '_', $message);

如何正确转义消息中的字符以获得异常或 PHP 错误?

我的 PHP 版本是 7.2

【问题讨论】:

  • 您的标题和您的问题不匹配且令人困惑,当您抛出异常时,它会导致Fatal error。你发现异常了吗?
  • 否,因为错误消息'some text '.inet_pton('119.252.33.171'); 本身会导致 Exception 类中的错误。在您的主机上运行我的示例并查看结果。
  • 我无法仅通过 inet_pton 调用重现该错误。你确定这是异常的原因吗?
  • @Miron 你确定是致命错误吗?在设置了 display_errors 和 E_ALL 的 7.2.11 上不会发生。致命错误的确切消息是什么?
  • &lt;br /&gt; &lt;b&gt;Fatal error&lt;/b&gt;: in &lt;b&gt;...&lt;/b&gt; on line &lt;b&gt;92&lt;/b&gt;&lt;br /&gt;

标签: php exception


【解决方案1】:

那是因为inet_pton() 不是要输出字符串,而是按网络顺序输出字节(我不记得是小端还是大端)。

异常消息不包括字节,而是可打印的字符。但是,您可以将纯字节放入字符串中。然后将它们解码为(可能)UTF-8 或其他编码以显示可读文本。

以下代码

$message = inet_pton('119.252.33.171');
var_dump($message);
for($i = 0; $i < strlen($message); $i++)
{
   echo ord($message[$i]) . "\n";
}

生产

string(4) "w�!�"
119
252
33
171

比较这两行

throw new \Exception(chr(33)); // Displays stacktrace
throw new \Exception(chr(252)); // Fails to output

我的猜测是当 PHP 尝试将字符串格式化为 UTF-8 以将异常消息打印到 stdout 时发生错误,但传入了无效的 UTF-8 字符串并且写入/解码失败。

无论如何,这似乎是 PHP 中的一个错误。

【讨论】:

  • 所以这是 PHP 错误 - 这是真的。仅在您的示例中最好使用 mb_ord()。
【解决方案2】:

您错误地使用了inet_pton(),因为它就是这样做的:

inet_pton — Converts a human readable IP address to its packed in_addr representation

您应该将地址附加到字符串而不调用inet_pton()

现在,关于错误。

在我从 5.5.12 到 7.2.8 的所有 PHP 设置中都不会出现该错误。 这是我从 PHP 5.5.12 收到的错误消息:

Fatal error: Uncaught exception 'Exception' with message 'some text wü!«' in C:\wamp\www\so\54584039.php:5 Stack trace: #0 {main} thrown in C:\wamp\www\so\54584039.php on line 5

我在其他版本中遇到了同样的“未捕获异常”错误,由https://3v4l.org/Klpep 确认。

这意味着错误必须是由 PHP 设置中出现的异常消息的后处理引起的 但不会发生在 3v4l.org 的设置和我的设置中。

我想到一个可能的罪魁祸首是html_errors 配置选项。 我将它设置为On 以了解会发生什么,果然,我得到了你的错误:

<br />
<b>Fatal error</b>:   in <b>C:\wamp\www\so\54584039.php</b> on line <b>5</b><br />

因此,解决方案是将您的html_errors 设置为Off

我强烈建议您始终将其设置为 Off, 因为如果您正在处理 JSON 输出(或其他格式),则 HTML 格式是无用的,它还会使错误消息更难阅读。

【讨论】: