찾다
백엔드 개발PHP 튜토리얼PHP5에서의 오류 처리 및 문제 위치 소개(코드 예)

이 글은 PHP5에서의 오류 처리 및 문제 위치에 대한 소개를 제공합니다(코드 예제). 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

PHP에서 E_ERROR 수준의 치명적인 런타임 오류가 발생했을 때 문제를 찾는 방법에 대해 이야기해 보겠습니다. 예를 들어 치명적인 오류: 허용된 크기의 메모리 메모리 오버플로입니다. 이런 종류의 오류가 발생하면 프로그램이 바로 종료됩니다. 오류가 보고된 특정 파일과 코드 줄 수를 나타내는 오류 로그가 PHP 오류 로그에 기록되며 다른 정보는 손실되지 않습니다. PHP7이라면 예외와 같은 오류를 잡을 수 있지만 PHP5에서는 그렇지 않습니다. Fatal error: Allowed memory size of内存溢出这种。当出现这种错误时会导致程序直接退出,PHP的error log中会记录一条错误日志说明报错的具体文件和代码行数,其它的任何信息都没有了。如果是PHP7的话还可以像捕获异常一样捕获错误,PHP5的话就不行了。

一般想到的方法就是看看报错的具体代码,如果报错文件是CommonReturn.class.php像下面这个样子。

<?php /**
 * 公共返回封装
 * Class CommonReturn
 */
class CommonReturn
{

    /**
     * 打包函数
     * @param     $params
     * @param int $status
     *
     * @return mixed
     */
    static public function packData($params, $status = 0)
    {
        $res[&#39;status&#39;] = $status;
        $res[&#39;data&#39;] = json_encode($params);
        return $res;
    }

}

其中json_encode那一行报错了,然后你查了下packData这个方法,有很多项目的类中都有调用,这时要怎么定位问题呢?

场景复现

好,首先我们复现下场景。假如实际调用的程序bug.php如下

<?php require_once &#39;./CommonReturn.class.php&#39;;

$res = ini_set(&#39;memory_limit&#39;, &#39;1m&#39;);

$res = [];
$char = str_repeat(&#39;x&#39;, 999);
for ($i = 0; $i < 900 ; $i++) {
    $res[] = $char;
}

$get_pack = CommonReturn::packData($res);

// something else

运行bug.php PHP错误日志中会记录

[08-Jan-2019 11:22:52 Asia/Shanghai] PHP Fatal error:  Allowed memory size of 1048576 bytes exhausted (tried to allocate 525177 bytes) in /CommonReturn.class.php on line 20

复现成功,错误日志中只是说明了报错的文件和哪行代码,无法知道程序的上下文堆栈信息,不知道具体是哪块业务逻辑调用的,这样一来就无法定位修复错误。如果是偶尔出现,并且没有来自前端业务的反馈要怎么排查呢。

解决思路

1、有人想到了修改memory_limit增加内存分配,但这种方法治标不治本。做开发肯定要找到问题的根源。

2、开启core dump,如果生成code文件可以进行调试,但是发现code只有进程异常退出才会生成。像E_ERROR级别的错误不一定会生成code文件,内存溢出这种可能PHP内部自己就处理了。

3、使用register_shutdown_function注册一个PHP终止时的回调函数,再调用error_get_last如果获取到了最后发生的错误,就通过debug_print_backtrace获取程序的堆栈信息,我们试试看。

修改CommonReturn.class.php文件如下

<?php /**
 * 公共返回封装
 * Class CommonReturn
 */
class CommonReturn
{

    /**
     * 打包函数
     * @param     $params
     * @param int $status
     *
     * @return mixed
     */
    static public function packData($params, $status = 0)
    {

        register_shutdown_function([&#39;CommonReturn&#39;, &#39;handleFatal&#39;]);

        $res[&#39;status&#39;] = $status;
        $res[&#39;data&#39;] = json_encode($params);
        return $res;
    }

    /**
     * 错误处理
     */
    static protected function handleFatal()
    {
        $err = error_get_last();
        if ($err[&#39;type&#39;]) {
            ob_start();
            debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
            $trace = ob_get_clean();
            $log_cont = &#39;time=%s&#39; . PHP_EOL . &#39;error_get_last:%s&#39; . PHP_EOL . &#39;trace:%s&#39; . PHP_EOL;
            @file_put_contents(&#39;/tmp/debug_&#39; . __FUNCTION__ . &#39;.log&#39;, sprintf($log_cont, date(&#39;Y-m-d H:i:s&#39;), var_export($err, 1), $trace), FILE_APPEND);
        }

    }

}

再次运行bug.php,日志如下。

error_get_last:array (
  'type' => 1,
  'message' => 'Allowed memory size of 1048576 bytes exhausted (tried to allocate 525177 bytes)',
  'file' => '/CommonReturn.class.php',
  'line' => 23,
)
trace:#0  CommonReturn::handleFatal()

回溯信息没有来源,尴尬了。猜测因为backtrace信息保存在内存中,当出现致命错误时会清空。没办法,把backtrace从外面传进来试试。再次修改CommonReturn.class.php。

<?php /**
 * 公共返回封装
 * Class CommonReturn
 */
class CommonReturn
{

    /**
     * 打包函数
     * @param     $params
     * @param int $status
     *
     * @return mixed
     */
    static public function packData($params, $status = 0)
    {

        ob_start();
        debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
        $trace = ob_get_clean();
        register_shutdown_function([&#39;CommonReturn&#39;, &#39;handleFatal&#39;], $trace);

        $res[&#39;status&#39;] = $status;
        $res[&#39;data&#39;] = json_encode($params);
        return $res;
    }

    /**
     * 错误处理
     * @param $trace
     */
    static protected function handleFatal($trace)
    {
        $err = error_get_last();
        if ($err[&#39;type&#39;]) {
            $log_cont = &#39;time=%s&#39; . PHP_EOL . &#39;error_get_last:%s&#39; . PHP_EOL . &#39;trace:%s&#39; . PHP_EOL;
            @file_put_contents(&#39;/tmp/debug_&#39; . __FUNCTION__ . &#39;.log&#39;, sprintf($log_cont, date(&#39;Y-m-d H:i:s&#39;), var_export($err, 1), $trace), FILE_APPEND);
        }

    }

}

再次运行bug.php

일반적으로 생각되는 방법은 에러 리포트의 구체적인 코드를 살펴보는 것입니다. 에러 리포트 파일이 CommonReturn.class.php라면 아래와 같습니다.

error_get_last:array (
  'type' => 1,
  'message' => 'Allowed memory size of 1048576 bytes exhausted (tried to allocate 525177 bytes)',
  'file' => '/CommonReturn.class.php',
  'line' => 26,
)
trace:#0  CommonReturn::packData() called at [/bug.php:13]
json_encode 라인에서 오류가 보고된 후 packData 메서드를 확인했습니다. 현재 문제를 어떻게 찾을 수 있나요?

장면 재현

  1. 자, 먼저 장면을 재현해 보겠습니다. 실제로 호출된 프로그램인 bug.php가 다음과 같다면

    rrreee

    bug.php를 실행하면 PHP 에러 로그에
  2. rrreee
  3. 이 기록됩니다. 재생에 성공하면 에러 로그가 나옵니다. 오류를 보고한 파일만 명시되어 있으며, 어떤 코드 줄에 대해서는 프로그램의 컨텍스트 스택 정보와 어떤 특정 비즈니스 로직이 호출되었는지 알 수 없으므로 오류를 찾아 수정하는 것이 불가능합니다. 간헐적으로 발생하는데 프론트엔드 업무에서 피드백이 없는 경우 문제 해결 방법.


    Solution

1. 어떤 사람들은 메모리 할당을 늘리기 위해 memory_limit를 수정하려고 생각했지만 이 방법은 증상을 치료할 뿐 근본 원인을 치료하지는 않습니다. 개발을 할 때에는 문제의 근본 원인을 찾아야 합니다.

    2.코드 파일이 생성되면 디버깅이 가능하지만, 프로세스가 비정상적으로 종료된 경우에만 코드가 생성되는 것으로 확인되었습니다. E_ERROR 수준의 오류는 반드시 코드 파일을 생성하지 않을 수도 있습니다. 메모리 오버플로 가능성은 PHP에서 내부적으로 처리됩니다.
  1. 3. PHP 종료 시 콜백 함수를 등록하기 위해 Register_shutdown_function을 사용하고, 마지막으로 발생한 오류가 발생하면 debug_print_backtrace를 사용하여 프로그램의 스택 정보를 얻으십시오.

  2. CommonReturn.class.php 파일을 다음과 같이 수정합니다.
rrreee
bug.php를 다시 실행하면 로그는 다음과 같습니다.

rrreee

트레이스백 정보에는 출처가 없어 당황스럽습니다. 역추적 정보는 메모리에 저장했다가 치명적인 오류가 발생하면 지워지기 때문인 것 같아요. 다른 방법은 없습니다. 외부에서 역추적을 전달해 보세요. CommonReturn.class.php를 다시 수정하세요. #🎜🎜#rrreee#🎜🎜#bug.php를 다시 실행하면 로그는 다음과 같습니다. #🎜🎜#rrreee#🎜🎜#bug.php의 13번째 줄에서 호출 소스를 성공적으로 찾았습니다. 최종 CommonReturn.class.php를 프로덕션 환경에 게시하고, 다시 오류가 발생하면 로그를 살펴보세요. 그러나 이 경우 packData를 호출하는 모든 프로그램은 추적 기능을 실행하므로 성능에 확실히 영향을 미칩니다. #🎜🎜##🎜🎜##🎜🎜#Summary#🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#사용된 Register_shutdown_function 함수에 주의해야 합니다. 여러 개의 다른 콜백을 등록할 수 있습니다. 하지만 특정 콜백 함수가 종료되면 나중에 등록된 콜백 함수는 모두 실행되지 않습니다. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#debug_print_backtrace 역추적 정보를 얻는 첫 번째 함수에는 요청 매개변수가 포함됩니다. 두 번째 함수는 역추적 레코드 레이어 수를 저장하기 위한 요청 매개변수를 반환하지 않습니다. 약간의 돈이 필요하며 요청 매개변수가 큰 경우 이 함수를 호출하면 메모리가 직접 오버플로될 수 있습니다. #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#가장 좋은 방법은 PHP7을 업그레이드하는 것인데, 예외와 같은 오류를 잡을 수 있습니다. . #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#

위 내용은 PHP5에서의 오류 처리 및 문제 위치 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 segmentfault.에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
교통량이 많은 웹 사이트를위한 PHP 성능 튜닝교통량이 많은 웹 사이트를위한 PHP 성능 튜닝May 14, 2025 am 12:13 AM

thesecrettokeepingAphp-poweredwebsiterunningsmoothlydlyUnderHeavyloadInvolvesEveralKeyStrategies : 1) ubstractOpCodeCachingWithOpCacheTecescripteExecutionTime, 2) usedatabasequeryCachingwithRedSendatabaseload, 3) LeverAgeCdnslikeCloudforforporerververforporporpin

PHP의 종속성 주입 : 초보자를위한 코드 예제PHP의 종속성 주입 : 초보자를위한 코드 예제May 14, 2025 am 12:08 AM

Code는 코드가 더 명확하고 유지 관리하기 쉽기 때문에 의존성 주입 (DI)에 관심을 가져야합니다. 1) DI는 클래스를 분리하여 더 모듈 식으로 만들고, 2) 테스트 및 코드 유연성의 편의성을 향상시키고, 3) DI 컨테이너를 사용하여 복잡한 종속성을 관리하지만 성능 영향 및 순환 종속성에주의를 기울이십시오. 4) 모범 사례는 추상 인터페이스에 의존하여 느슨한 커플 링을 달성하는 것입니다.

PHP 성능 : 응용 프로그램을 최적화 할 수 있습니까?PHP 성능 : 응용 프로그램을 최적화 할 수 있습니까?May 14, 2025 am 12:04 AM

예, PPAPPLICATIONISPOSSIBLEADESLESTION.1) INVERECINGUSINGAPCUTERODUCEDABASELOAD.2) INCODINCEDEXING, ENGICIONEQUERIES 및 CONNECTIONPOULING.3) 향상된 보드 바이어링, 플로 팅 포르코 잉을 피하는 최적화 된 APPCUTERODECEDATABASELOAD.2)

PHP 성능 최적화 : 궁극적 인 가이드PHP 성능 최적화 : 궁극적 인 가이드May 14, 2025 am 12:02 AM

theKeyStrategiesToSINCINTIFILINTINTIFILINTINTHPPORMATIONPERFORMANCEARE : 1) USEOPCODECACHING-CCHACHETEDECUTECUTINGTIME, 2) 최적화 된 ABESINSTEMENTEMENDSTEMENTEMENDSENDSTATEMENTENDS 및 PROPERINDEXING, 3) ConfigureWebSerVERSLIKENGINXXWITHPMFORBETPERMERCORMANCES, 4)

PHP 의존성 주입 컨테이너 : 빠른 시작PHP 의존성 주입 컨테이너 : 빠른 시작May 13, 2025 am 12:11 AM

aphpdectionenceindectioncontainerisatoolthatmanagesclassdependencies, 향상 Codemodularity, testability 및 maintainability.itactAsacentralHubForCreatingAndingDinjectingDingingDingingdecting.

PHP의 종속성 주입 대 서비스 로케이터PHP의 종속성 주입 대 서비스 로케이터May 13, 2025 am 12:10 AM

대규모 응용 프로그램의 경우 SELLENCIONINGESS (DI)를 선택하십시오. ServicElocator는 소규모 프로젝트 또는 프로토 타입에 적합합니다. 1) DI는 생성자 주입을 통한 코드의 테스트 가능성과 모듈성을 향상시킵니다. 2) Servicelocator는 센터 등록을 통해 서비스를 얻습니다. 이는 편리하지만 코드 커플 링이 증가 할 수 있습니다.

PHP 성능 최적화 전략.PHP 성능 최적화 전략.May 13, 2025 am 12:06 AM

phPapplicationSCanBeoptimizedForsPeedandefficiencyby : 1) ENABLEOPCACHEINPHP.INI, 2) PREPAREDSTATEMENTSWITHPDOFORDATABASEQUERIES 사용

PHP 이메일 검증 : 이메일이 올바르게 전송되도록합니다PHP 이메일 검증 : 이메일이 올바르게 전송되도록합니다May 13, 2025 am 12:06 AM

phpeMailValidationInvoLvestHreesteps : 1) formatValidationUsingRegularexpressionsTochemailformat; 2) dnsValidationToErethedomainHasaValidMxRecord; 3) smtpvalidation, theSTHOROUGHMETHOD, theCheckSiftheCefTHECCECKSOCCONNECTERTETETETETETETWERTETWERTETWER

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경