PHP 오류 억제기 @로 인해 참조 매개변수 전송이 실패하는 버그 분석

WBOY
풀어 주다: 2016-07-29 08:45:03
원래의
1059명이 탐색했습니다.

아래 예를 보세요.

코드 복사 코드는 다음과 같습니다.


$ array = array(1 ,2,3);
함수 추가(&$arr) {
$arr[] = 4
}
add(@$array)
print_r; ($array);
/**
현재 $array는 변경되지 않았습니다. 출력:
Array
(
[0] => 1
[1] => 2
[2] = >3
)
*/
add($array)
print_r($array)
/**
오류 억제가 없으면 출력은 정상입니다.
배열
(
[0] => 1
[1] => 2
[2] => ; 3
[3] => 4
)
*/
?> ;


저는 이 문제를 겪은 적이 없어서 먼저 관련 정보를 찾아보고 미리 준비된 답변이 있는지 확인했습니다. PHP와 유사한 버그 :http://bugs.php.net/bug.php?id=47623, PHP 관계자는 아직까지 해결하지 못하고 답변도 하지 않았습니다.

그 밖에는 없습니다. 오류 억제의 원리는 기사에 소개되어 있습니다(PHP의 오류 억제 원리 및 내장 HTML에 대한 심층적인 이해). 원칙적으로 오류 억제는 수준만 수정합니다. error_reporting이며 논리적으로 말하면 호출 메커니즘은 현장에서만 테스트할 수 있습니다.

gdb로 추적한 결과 잘못된 이식 문자를 사용한 후에 발견되었습니다. 함수 호출 전의 매개변수 opcode가 다릅니다:

코드 복사 코드는 다음과 같습니다:


// 오류 억제기가 사용되지 않음
OPCODE = SEND_REF
//에러 억제기가 사용된 후
OPCODE = SEND_VAR_NO_RE


문제가 처음에 발견되었지만 그 이유는 무엇입니까? 이 차이는?
OPCODE가 다르기 때문에 구문 분석 단계에서 다른 분기를 수행해야 합니다. 이제 이 수준을 생각하면 문제를 쉽게 식별할 수 있습니다.
이는 PHP 구문 분석에서 알 수 있습니다. 단계에서 "@" expr 형식의 항목은 expr_without_variable로 축소되며 이러한 종류의 노드의 의미는 변수가 없는 값, 즉 리터럴 값이 참조를 전달할 수 없다는 것을 우리 모두 알고 있습니다. 변수가 아니기 때문에), 이러한 차이가 발생하게 됩니다.
구체적인 과정은 다음과 같습니다.
1. 구문 분석 단계:

코드 복사 코드는 다음과 같습니다.


expr_without_variable:
//...with omission
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC) }
expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
//ZEND_SEND_VAL 분기가 여기에서 사라졌습니다
non_empty_function_call_parameter_list:
expr_without_variable { ... .} //이 분기로 잘못 이동했습니다
| 변수 {..... } //정상적인 상황


이므로 컴파일 중에 다른 OPCODE가 생성되어 문제가 발생하게 됩니다.
마지막으로 이유를 설명했습니다. 관심이 있으시면 이 PHP 버그 페이지에서 저의 부족한 영어 실력을 확인하실 수 있습니다. 마지막으로 흥미로운 질문을 제공해 주신 cici 네티즌에게 감사드립니다.

위 내용을 포함하여 PHP 오류 억제기@에서 참조 매개변수 전송 실패를 일으키는 버그에 대한 분석을 소개합니다. PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿