2014-12-28 2 views
1

주 데이터는 주에서 정의 된 세 개의 double입니다. variadic 함수 인 wrapperVariadic을 가져 와서 합계가 strictly이면 true를 반환합니다. 주어진 숫자는 모두 작고 긍정적이어서 결과는 사실이어야합니다.
wrapperVariadic 모든 숫자의 합계를 얻으려면 summerVariadic을 호출하십시오.
summerVariadic 후 벡터에 포함 된 모든 숫자의 계산에 대한 합계 summerNonVariadic 전화 이중 표준 : : 벡터에 각 번호를 넣어.Valgrind 가변 인수 함수의 체인 된 호출을 사용할 때 조건부 점프 또는 이동은 단위화된 값에 따라 달라집니다.

문제점 : va_args가 인 경우 summerVariadic은 항상 0입니다. 최종 실행 파일에 valgrind을 사용하면 "조건부 점프 또는 이동이 unitified 된 값 ("에 종속 됨)이 주에서 발견됩니다. 에 따르면 --track-origin = yes 옵션의 원점은 입니다. 초기화되지 않은 값은 스택 할당에 의해 생성되었습니다.

세 가지 기능을 사용했을 때 런타임

// simple vector summer 
float summerNonVariadic(const std::vector<double> values) { 
     float sum = 0.; 
     for(unsigned int summed = 0; summed < values.size(); summed++) { 
       sum += values[summed]; 
     } 
     return sum; 
} 



// put the n doubles in a vector, and call summerNonVariadic. 
float summerVariadic(const unsigned int n, ...) { 
     std::vector<double> values; 
     va_list args; 
     va_start(args, n); 

     for(unsigned int j = 0; j < n; j++) { 
       values.push_back(va_arg(args, double)); 
       //printf("AIG:%f\n", values.back()); 
       // printf call show that pushed values are always equal to zero, 
       // and generates lots of "Conditional jump" valgrind error 
     } 

     va_end(args); 
     return summerNonVariadic(values); 
} 



// the wrapper 
bool wrapperVariadic(const unsigned int n, ...) { 
     va_list args; 
     va_start(args, n); 
     float summer_said = summerVariadic(n, args); 
     va_end(args); 
     return summer_said > 0; 
} 

매크로는 다음

#define LOGOK fprintf(stderr,"OK:%s:%u\n", __FILE__, __LINE__); 

주요 기능을 MAIN.CPP에서 :

int main(int argc, char* argv[]) { 
     double a = 4.2, b = 5.1, c = 0.3; 
     bool bool_res = wrapperVariadic(3, a, b, c); 
     LOGOK // line 125 
     if(bool_res) { 
       LOGOK // line 127, never reached 
     } 
     LOGOK // line 129 

     return EXIT_SUCCESS; 
} 

통화 Valgrind의 :

01 23,516,
valgrind --leak-check=full --track-origins=yes ./a.out 

최종 출력 :

==8624== Memcheck, a memory error detector 
==8624== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==8624== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==8624== Command: ./a.out 
==8624== 
OK:main.cpp:125 
==8624== Conditional jump or move depends on uninitialised value(s) 
==8624== at 0x40B9AD: main (main.cpp:126) 
==8624== 
OK:main.cpp:129 
==8624== 
==8624== HEAP SUMMARY: 
==8624==  in use at exit: 0 bytes in 0 blocks 
==8624== total heap usage: 4 allocs, 4 frees, 80 bytes allocated 
==8624== 
==8624== All heap blocks were freed -- no leaks are possible 
==8624== 
==8624== For counts of detected and suppressed errors, rerun with: -v 
==8624== Use --track-origins=yes to see where uninitialised values come from 
==8624== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) 

우리는 최종 값 때문에 에서 벡터의 두 배 값의 나쁜 독서 summerNonVariadic의, 거짓 볼 수 있습니다.

메인의 행 124를 으로 바꾸십시오. bool_res = summerVariadic (3, a, b, c); 모든 오류를 제거하고 예상 된 결과를 생성하십시오. (OK : main.cpp : 127)

이 가변 가변 함수 호출의 문제점은 무엇입니까?

버전 : 당신이 summerVariadic(n, args);를 사용할 때

gcc version 4.7.2 (Debian 4.7.2-5) 
+0

난 당신이 -g''로 컴파일의 Valgrind의 출력에 어떤 줄 번호가 표시되지 않습니다

C++ (11) 때문에, 당신은 대신 가변 인자 템플릿을 사용할 수 있나요? 그렇다면 점프는 어떤 라인에서 발생합니까? –

+0

@RyanHaining valgrind 출력에 표시된 행이 없습니다. 점프는 메인의 126 행에서'if (bool_res) {'에서 발생합니다. bool_res는 단위화된 값으로 나타납니다. 나는'-g' 플래그를 사용하여 게시물을 업데이트 할 것입니다. – aluriak

답변

4

, 당신은 float summerVariadic(const unsigned int n, va_list args)를 제공해야합니다.

template<typename ... Ts> 
float summerVariadic(Ts... args) { 
    return summerNonVariadic({args...}); 
} 
+0

완벽한 솔루션! 하지만 순수한 C 코드에서는 처음에는 못생긴 해결책 이었습니까? summerVariadic은 'float summerVariadic (const unsigned int n, va_list args)'로 정의됩니다. 일반적인 가변 함수로 사용할 수 없습니까? – aluriak

+1

@aluriak : 순수한 C에서는'std :: vector'가 없습니다. 줄임표 대신에 부동 배열을 사용할 수도 있습니다. 거의 각 줄임표 기능을 가지고 (및 통화) va_list''와 동등한 기능을, 그래서 당신은 va_list' '또는 생략 부호로, 모두를 호출 할 수 있습니다. – Jarod42

관련 문제