2012-01-29 1 views
0

서버 버전을 업데이트해야하는 시나리오가 있습니다. g ++ 버전을 사용하면 새로운 버전에서 오류가 발생하기 시작한 코드가 실제로 세그먼트 화됩니다. 결점).잠재적 인 버그를 발견 한 C++ 최적화 수준

#include<stdio.h> 
int main() 
{ 
     char s[8]={'\0'}; 
     sprintf(s,"overflow"); 
     return 1; 
} 

컴파일했다가 g ++가 file.cc -O2

우리가 지정하는대로 따라서 최적화 오류가 발생할 한 전체 문자열 S : 그런 다음 코드를 디버깅,이 같은 뭔가 깨달았다 , 그리고 NULL 종료가 없습니다. 위의 오류가 잘못된 프로그래밍 관행으로 인해 빠질 수 있으므로 g ++의 다른 버전으로 이동할 때 특히 최적화 플래그를 ON으로 사용하는 것이 좋습니다.

+4

잘못된 코드는 잘못된 코드입니다. 너는 운이 좋았어. 전에는 충돌하지 않았어. –

+6

또는 불행 해 ... –

+0

C++ ('c_str()'에서 문자열 대신 char 배열을 사용하는 이유는'const char *'가 필요한 대부분의 시나리오에 충분합니다. 그렇지 않으면 복사본을 만들 수 있습니다 그리고 거기에) 그리고 이것은 이것이 왜 그렇게 좋은지 보여주는 좋은 예입니다. – Voo

답변

6

오류는 코드에 있습니다. 오류를 볼 수없는 최적화 플래그가없는 사실은 불행입니다.

물론 옵티 마이저에는 버그가있을 수 있지만 현재 gcc는 -O2으로 드물게 코드를 생성합니다. 일반적으로 일반적인 최적화 플래그를 피할 이유가 없습니다.

이 예제는 최적화를 피하는 이유보다 다양한 메모리 검사 옵션과 프로필러를 사용하여 다양한 옵션으로 컴파일하는 것이 더 바람직하기 때문입니다.

+0

가능하면 다른 컴파일러, 다른 플랫폼 및 다른 라이브러리를 사용하십시오. –

3

오류는 코드입니다. 코드에는 정의되지 않은 동작이 할당 메모리 영역 경계를 초과하여 씁니다. 당신은 운 좋았거나 운이 좋았습니다. 이전에는 이상한 행동을 보이지 않았고 지금은 단지 그것을 보여줍니다.

이것은 최적화 플래그 사용과 관련이 없으며 정의되지 않은 동작을 나타내는 나쁜 코드의 일반적인 경우입니다. 당신이 정의되지 않은 동작와 코드가있을 때

이 모든 안전 내기가 꺼져 있고 당신은 하나 개의 법에 보장받을 수 있으며, 머피의 법 : 아마도 잘못 될 수

아무것도,하지

0

코드에 결함이 있습니다. 최적화가 이유가 아닙니다. sprintf은 끝에 null 문자를 추가하지만 s에는 충분한 공간이 없습니다.

char s[9]; //9 atleast! 

또는 std::strncpy으로 사용 :

그래서 수정으로 s를 선언 중 하나입니다

std::strncpy(s, "overflow", 8); 

은 사용 후, 정상적인 C - 문자열로 s을 사용하려고하고있는 경우 첫 번째 접근법.

0

귀하의 질문을 이해할 수 없을 것입니다. 위의 오류는 최적화 설정에 관계없이 존재합니다. 정의되지 않은 동작을 호출했습니다. 런타임에서 하드 드라이브를 포맷하는 것이 아니라 정상적으로이를 감지 할 수있어서 감사합니다.

이 솔루션은 컴파일러 최적화를 피하는 것이 아니라 UB를 호출하는 것을 피하는 것입니다.

0

당신이 묻는 질문은 그렇게 중요하지 않습니다 - 프로그램은 정의되지 않은 행동에 의존합니다. 그런 의미에서 최적화는 버그를 확인했으며, 그것에 대해 만족해야합니다.

일부 최적화는 오류를 발생시킬 수 있습니다 (예 : 모든 부동 소수점 값이 Inf 또는 NaN이 아닌 것으로 가정). 그러나이 중 하나만있는 것은 아닙니다.

2

최적화로 인해 오류가 발생하지 않았습니다. 컴파일러 버전 및/또는 컴파일러 구성 (이 경우 어쩌면 최적화 일 수도 있음)을 변경하면 기존 오류가 노출 될 수 있습니다. 이러한 이전 이러한 버그를 색출하기 위해 Valgrind의 같은 도구와

  • 시험 : 다음 중 하나 이상이 될 수 있습니다이 버그 때문에 당신이 촉발 될 수

    좋은 방법은 미래에 걸릴

  • 또는 std::string과 같이 오버플로를 방지하는 데 도움이되는 함수 나 클래스를 사용하는 것이 안전하지 않은 sprintf()과 같은 함수는 부적절하게 사용하지 않는 것이 좋습니다.
-1

먼저 -이 코드는 유용하지 않습니다. 둘째, 9 바이트를 8 바이트 버퍼에 씁니다. 세 번째 - Ascii 문자열은 끝 기호로 NULL로 끝나야하며 9 번째 코드를 8 바이트 버퍼에 넣을 공간이 없습니다. Forth - 왜 로컬 버퍼에 문자열을 넣고 아무 것도하지 않아도됩니까?

관련 문제