선사 시대는 : C에서 분할을 테스트에도 불구하고 0으로 프로그램 제기 부문 ++ :나누기 ++ 2015
우리는 단지 우리가 문제를 발견 그 후 VC++ 2008 오른쪽에서 ++ 2015 VC에 우리의 개발 환경을 전환 한 암호.
테스트 코드 : 기본 릴리스 옵션 VC++ 2015 업데이트 3 또는 VC++ 2017 컴파일
#include <cstdlib>
int test(int n, int test_for_zero)
{
int result = 0;
for (int i = 0; i < n; ++i) {
if (test_for_zero)
result += rand() >> ((8 % test_for_zero) * test_for_zero);
}
return result;
}
int main()
{
return test(rand(), rand() & 0x80000000);
}
, 그것은 0으로 나누기를 제기 실행에. VC 2008에 의해 컴파일 된 잘 실행됩니다.
분석 :
; 6 : for (int i = 0; i < n; ++i) {
test edi, edi
jle SHORT [email protected]
; 7 :
; 8 : if (test_for_zero)
; 9 : result += rand() >> ((8 % test_for_zero) * test_for_zero);
mov ecx, DWORD PTR _test_for_zero$1$[ebp]
mov eax, 8
cdq
idiv ecx ; <== IT'S HERE, IDIV BEFORE CHECKING FOR ZERO
mov eax, edx
imul eax, ecx
mov DWORD PTR tv147[ebp], eax
test ecx, ecx
je SHORT [email protected]
[email protected]:
call ebx
mov ecx, DWORD PTR tv147[ebp]
sar eax, cl
add esi, eax
sub edi, 1
jne SHORT [email protected]
컴파일러는 루프 본문에서 일정 부분 ((8 % test_for_zero) * test_for_zero)
소요 단지 분할하기 전에 테스트 test_for_zero
에 대해 잊어 버려. 분명히 컴파일러 작업을 수행하는 것만으로 장소에서 쉽게 수정할 수 있습니다.
나는 여러 컴파일러 옵션 (예 : -d2SSAOptimizer-
및 -Oxx
)을 사용했지만이 문제를 해결할 수있는 유일한 방법은 -Od
입니다.
질문 :
- 는 버그인지? VC 2008 이후로 C++ 표준이 크게 변경되었으므로 이런 영향을받을 수 있습니까?
- 주 질문은 컴파일러 옵션을 통해 문제를 해결할 수있는 해결 방법이 있습니까?
이 질문에 대한 답변을하지 않지만 해당 변수가 0이면 루프를 건너 뛰는 것이 더 합리적이지 않습니까? 당신은 결코 그것을 바꿀 수 없기 때문에, 하나의 반복에서 0이라면, 그것들 모두에 대해 0이 될 것이고,이 경우 루프는 아무것도하지 않는다. – Carcigenicate
또한 숫자가 진실인지 확인하는 대신 0을 확인하기 위해 조건을 변경하면 어떻게됩니까? 상관 없지만이 오류는 의미가 없습니다. – Carcigenicate
중괄호도 부족할 수 있습니다. Idk는 정확히 어떻게 C++이 그런 구문을 파싱 하는지를 설명합니다. 중괄호를 추가하십시오. – Carcigenicate