2017-12-14 18 views
0

배열에서 항목을 인라인하지 않는 C 컴파일러를 강제 :내가 C의 함수 포인터의 배열을 가지고

int f1 (void) { 
    return 1; 
} 
int f2 (void) { 
    return 2; 
} 
int (*const functions[])(void) = {f1, f2}; 
코드의 다른

어딘가에 (타사 도구를 사용하여), 나는의 내용을 파괴 함수 배열을 사용하기 전에. 따라서 ,

result = functions[0](); 

가 아닌 정의 행동 (실행중인 프로그램의 경우에도 낙태) 발생한다. 그러나 그렇지 않습니다. 결과는 마치 파괴가 일어난 적이없는 것처럼 보입니다.

현재, 나는이 문제에 대한 오류의 두 가지 소스를 상상할 수 :

  1. 파괴가 컴파일러는 컴파일시에 배열의 내용을 인라인 따라서, 파괴 효과가 없습니다
  2. 발생하지 않습니다.

지금까지 제 3 자 도구는 파괴 된 내용을 파괴하지 않는 동작을 보여주지 못했습니다. 그러므로 나는 후자를 추측해야만한다.

어떻게 함수 배열의 내용을 인라인하지 못하게 할 수 있습니까?

+3

함수 포인터는'const'이므로 변경할 수 없습니다. – mch

+1

mch가 말한 바. UB가 다른 UB에 있기 때문에 코드의 한 부분에서 "예상 된"UB를 얻지 못한다는 점에 놀랍니다. – StoryTeller

+0

[MCVE]를 게시 할 수 있습니까? 생성 된 어셈블리 코드를 살펴보십시오. 디버거를 사용하십시오. –

답변

2

배열을 const으로 선언했기 때문에 컴파일러가 함수를 인라인 할 수 있으며 volatile이 아닙니다. 따라서 추상 실행 모델에 따르면, 배열이 결코 변경되지 않는다고 가정 할 수 있습니다.

배열을 변경할 수 있도록하려면 const을 제거해야합니다.

컴파일러가 다른 곳에서 변경 사항을 적용하려면 volatile을 추가해야합니다.

+0

보다 정확하게는 컴파일러는 배열 내용이 변경되지 않는다고 가정 할 수 있습니다. '선언 된 타입을 가진 배열을 전달했다면 다른 포인터를 통해 어떤 요소가 변경 될 가능성이 있습니다 –

+0

어떤 것이'const volatile'이라면 그것들은 단지 선언 된 것이 아니기 때문에 나는 C 컴파일러의 표준 인용문을 가지고 있지는 않지만'const'에도 불구하고 컴파일러에게 모든 사용을로드 할 것을 요구한다. –

+0

아니,별로 중요하지 않다. const가 정의되고 선언 된 경우에만 해당되는 차이점은 volatile이 아니고 두 개의 액세스간에 다른 함수 호출이 없으면 컴파일러는 아무 것도 변경되지 않았다고 가정 할 수 있습니다. 너를 도울 뿐이다. 컴파일러는 당신이 수정하는 것을 허락하지 않을 것이고, 그것이 바꿀 수 없다면 말하지 않을 것이다. –

0

당신의 오류 시나리오는 나에게 많은 이해가되지 않습니다,하지만 우리가 무시한다면, 당신은 다음과 같이 인라인을 방지 할 수 있습니다 :

typedef int func_t (void); 

volatile func_t* const[] = {f1, f2}; 

이 컴파일러가 배열의 첫 번째 항목을 기대할 수 없다는 것을 의미합니다 항상 f1이어야하며 최적화가 불가능합니다. volatile은 호출하기 전에 함수 포인터 주소를 강제로 읽습니다. 즉, 주소가 있어야합니다. 즉, 인라인 된 함수에 주소가 없으므로 인라인이 불가능하다는 것을 의미합니다.