왜이 C ++ 스 니펫 컴파일 (비 공백 함수가 값을 반환하지 않음)
이 질문에는 이미 답변이 있습니다.
오늘 아침 내 도서관 중 하나에서 이것을 발견했습니다.
static tvec4 Min(const tvec4& a, const tvec4& b, tvec4& out)
{
tvec3::Min(a,b,out);
out.w = min(a.w,b.w);
}
이 메소드는 아무것도 반환하지 않고 반환 유형이 아니기 때문에 컴파일러 오류가 발생할 것으로 예상 void
됩니다.
떠오르는 유일한 두 가지는
이 메소드가 호출되는 유일한 위치에서는 리턴 값이 사용되거나 저장되지 않습니다. (이 방법은 있어야했다
void
-tvec4
반환 형식은 복사하여 붙여 넣기 오류입니다)tvec4
C ++의 다른 모든 것과는 다르게 보이는 기본 생성 이 작성됩니다.
이 문제를 해결하는 C ++ 사양의 일부를 찾지 못했습니다. 참고 문헌 (ha)이 인정된다.
최신 정보
에서 어떤 상황이 VS2012에서 오류가 발생합니다. 나는 세부 사항을 좁히지 않았지만 그럼에도 불구하고 흥미 롭습니다.
입니다 정의되지 않은 동작 로부터 C ++ 11 초안 표준 섹션 6.6.3
반환 문 제 2 말합니다 :
[...] 함수의 끝에서 흘러 나오는 것은 값이없는 리턴과 같습니다. 이로 인해 값 반환 함수에서 정의되지 않은 동작이 발생합니다. [...]
이는 컴파일러가 모든 경우에 진단하기 어려울 수 있으므로 일반적으로 오류나 경고를 제공 할 의무가 없음을 의미합니다. 우리는 표준 초안 의 정의되지 않은 행동 의 정의에서 이것을 볼 수 있습니다 1.3.24
:
[...] 허용되지 않은 정의 된 동작은 예측할 수없는 결과로 상황을 완전히 무시하는 것, 번역 또는 프로그램 실행 중 환경의 문서화 된 방식으로 (진단 메시지 발행 여부에 관계없이) 동작, 번역 종료 또는 실행 (진단 메시지 발행). [...]
이 경우 우리는 모두를 얻을 수 있지만 gcc
및 clang
사용하여 wanring를 생성하는 -Wall
나에게 다음과 유사한 경고를 제공 플래그를 :
경고 : 제어가 비 공백 기능의 끝에 도달합니다. [-Wreturn-type]
-Werror=return-type
플래그를 사용하여이 특정 경고를 오류로 바꿀 수 있습니다 . 나는 또한 -Wextra -Wconversion -pedantic
내 자신의 개인 프로젝트 에 사용 하고 싶습니다.
ComicSansMS가 Visual Studio 에서 언급 했듯이이 코드는 기본적으로 오류 인 C4716 을 생성 합니다. 내가 보는 메시지는 다음과 같습니다.
오류 C4716 : '최소': 값을 반환해야합니다
모든 코드 경로가 값을 반환하지 않는 경우 경고 인 C4715를 생성 합니다.
아마도 질문 의 이유 부분 에 대한 약간의 설명이있을 수 있습니다 .
결과적으로 C ++ 컴파일러는 함수가 반환 값없이 종료되는지 여부를 판단하기가 실제로 매우 어렵습니다 †. 명시적인 return 문으로 끝나는 코드 경로와 함수의 끝에서 나오는 코드 경로 외에도 longjmp
함수 자체뿐만 아니라 모든 호출 수신자에서 예외 예외 또는 s 를 고려해야 합니다.
컴파일러가 리턴이 누락 된 것처럼 보이는 함수를 식별하는 것은 매우 쉽지만 리턴 이 누락되었음을 증명 하는 것은 상당히 어렵습니다 . 이 부담의 컴파일러 공급 업체를 높이기 위해 표준에서는 오류 발생을 요구하지 않습니다.
따라서 컴파일러 공급 업체는 함수에 리턴 값이 없다고 확신하고 컴파일러가 실제로 잘못된 경우에 해당 경고를 무시 / 마스크 할 수있는 경우 경고를 자유롭게 생성 할 수 있습니다.
† : 일반적인 경우 이는 정지 문제 와 동일 하므로 실제로 기계가이를 안정적으로 결정하는 것은 불가능합니다.
-Wreturn-type
옵션으로 코드를 컴파일하십시오 .
$ g++ -Wreturn-type source.cpp
이것은 당신에게 줄 것이다 경고 . 너무 사용하면 경고를 오류 로 바꿀 수 있습니다 -Werror
.
$ g++ -Wreturn-type -Werror source.cpp
이렇게하면 모든 경고가 오류로 바뀝니다 . 따라서 특정 경고에 대한 오류를 원한다면 다음과 같이 부분 없이 -Wreturn-type
입력하십시오 .return-type
-W
$ g++ -Werror=return-type source.cpp
일반적으로 항상 -Wall
가장 일반적인 경고가 포함 된 옵션을 사용해야 합니다. 여기에는 누락 된 return 문도 포함됩니다. 와 함께 -Wall
,에 -Wextra
포함되지 않은 다른 경고를 포함하여 사용할 수도 있습니다 -Wall
.
아마도 질문 의 이유 부분 에 대한 추가 설명이있을 수 있습니다.
C ++는 매우 많은 기존 C 코드 본문이 최소한의 변경으로 컴파일되도록 설계되었습니다. 불행히도 C 자체는 void
키워드 조차 없었고 대신 기본 반환 유형 인에 의존 하는 가장 이른 사전 표준 C와 유사한 의무를 지불했습니다 int
. C 함수는 일반적으로 값을 반환했으며 Algol / Pascal / Basic 프로 시저와 표면적으로 유사한 코드가 아무런 return
언급 없이 작성 될 때마다 함수는 스택에 남아있는 쓰레기를 반환합니다. 발신자 나 수신자 모두 신뢰할 수있는 방식으로 쓰레기 값을 할당하지 않습니다. 그런 다음 모든 호출자가 가비지를 무시하면 모든 것이 정상이며 C ++은 그러한 코드를 컴파일해야한다는 도덕적 의무를 상속합니다.
(호출자가 반환 된 값을 사용하는 경우 초기화되지 않은 변수의 처리와 유사하게 코드가 비 결정적으로 작동 할 수 있습니다. C에 대한 가상의 후속 언어에서 컴파일러가 차이를 확실하게 식별 할 수 있습니까? 발신자와 수신자는 서로 다른 편집 단위에있을 수 있습니다.)
내재 int
는 여기에 관련된 C 레거시의 일부일뿐입니다. "디스패처"함수는 매개 변수에 따라 일부 코드 분기에서 다양한 유형을 반환하고 다른 코드 분기에서는 유용한 값을 반환하지 않을 수 있습니다. 이러한 함수는 일반적으로 가능한 유형을 보유하기에 충분한 유형을 반환하도록 선언되며 호출자는 해당 유형을 캐스팅하거나에서 추출해야 할 수도 있습니다 union
.
So the deepest cause is probably the C language creators' belief that procedures that do not return any value are just an unimportant special case of functions that do; this problem got aggravated by the lack of focus on type safety of function calls in the oldest C dialects.
While C++ did break compatibility with some of the worst aspects of C (example), the willingness to compile a return statement without a value (or the implicit value-less return at the end of a function) was not one of them.
As already mentioned, this is undefined behavior and will give you a compiler warning. Most places I've worked require you to turn on compiler settings to treat warnings as errors - which enforces that all your code must compile with 0 errors and 0 warnings. This is a good example of why that is a good idea.
This is more of the standard C++ rule/feature which tends to be flexible with things and which tends to be more close to C.
But when we talk of the compilers, GCC or VS, they are more for professional usage and for variety of development purposes and hence put more strict development rules as per your needs.
That makes sense also, my personal opinion, because the language is all about features and its usage whereas compiler defines the rules for optimal and best way of using it as per your needs.
As mentioned in above post, compiler sometimes gives the error, sometimes gives warning and also it has the option of skipping these warning etc, indicating the freedom to use the language and its features in a way that suits us best.
Along with this there are several other questions mentioning this behaviour of returning a result without having a return
statement. One simple example would be:
int foo(int a, int b){ int c = a+b;}
int main(){
int c = 5;
int d = 5;
printf("f(%d,%d) is %d\n", c, d, foo(c,d));
return 0;
}
Could this anomaly be due stack properties and more specifically:
Zero-Address Machines
In zero-address machines, locations of both operands are assumed to be at a default location. These machines use the stack as the source of the input operands and the result goes back into the stack. Stack is a LIFO (last-in-first-out) data structure that all processors support, whether or not they are zero-address machines. As the name implies, the last item placed on the stack is the first item to be taken out of the stack. All operations on this type of machine assume that the required input operands are the top two values on the stack. The result of the operation is placed on top of the stack.
In addition to that, for accessing memory to read and write data same registers are used as data source and destination(DS (data segment) register), that store first the variables needed for the calculation and then the returned result.
Note:
with this answer I would like to discuss one possible explanation of the strange behaviour at machine (instruction) level as it has already a context and its covered in adequately wide range.
'Programing' 카테고리의 다른 글
문자열에서 모든 공백을 제거하는 방법은 무엇입니까? (0) | 2020.07.02 |
---|---|
코드의 "복사 및 붙여 넣기"가 위험한 이유는 무엇입니까? (0) | 2020.07.02 |
문자열에 배열의 문자열이 포함되어 있는지 테스트 (0) | 2020.07.02 |
@ManyToOne 속성에는 @Column이 허용되지 않습니다. (0) | 2020.07.02 |
페이스 북 데이터베이스 디자인? (0) | 2020.07.02 |