2010-05-28 3 views
0

나는 내가 유지 관리중인 일부 레거시 코드에서 다음 기능을 가지고있다.variadic 함수의 문제

long getMaxStart(long start, long count, const myStruct *s1, ...) 
{ 
    long  i1, maxstart; 
    myStruct *s2; 
    va_list marker; 

    maxstart = start; 

    /*BUGFIX: 003 */ 
    /*(va_start(marker, count);*/ 
    va_start(marker, s1); 

    for (i1 = 1; i1 <= count; i1++) 
    { 
     s2 = va_arg(marker, myStruct *);   /* <- s2 is assigned null here */ 
     maxstart = MAX(maxstart, s2->firstvalid); /* <- SEGV here */ 
    } 

    va_end(marker); 
    return (maxstart); 
} 

하나의 myStruct 인수 만 사용하여 함수를 호출하면 SEGV가 발생합니다. 이 코드는 VS2005를 사용하여 컴파일 할 때 Windows XP에서 충돌없이 컴파일되고 실행됩니다. 이제 우분투 커널로 코드를 옮겼고 Linux에서 더 엄격한 컴파일러에 문제가 있습니다. 아무도 매개 변수가 var_arg() 문에서 올바르게 읽히지 않는 원인을 찾아 낼 수 있습니까?

start = getMaxStart(start, 1, ms1); 

변수 '시작'과 'MS1': 나는 버전의 gcc를 사용하여 컴파일하고

편집

SEGV를 일으키는 문이 하나

입니다 4.4.1 코드 실행이이 행에 처음 도달 할 때 유효한 값을가집니다.

+2

당신이 말하는 코드는 어떻게 생겼습니까? –

답변

4

작성한대로 myStruct 인수를 하나만 전달하면 s1이 해당 인수에 바인딩되고 va_list은 비어 있습니다. 그런 다음 루프에서 가장 먼저하는 일은 빈 목록에서 인수를 얻는 것입니다. 따라서 NULL입니다. 당신은 적어도 하나 개의 인수를 필요로하고 컴파일러가 당신을 위해 입력-확인하려면

, 당신이 이런 식으로 뭔가를해야 할 것 :

long getMaxStart(long start, long count, const myStruct *s1, ...) { 
    ... 
    va_start(marker, s1); 
    maxstart = s1->firstvalid; /* actually use s1 this time! */ 
    for (i1 = 1; i1 < count; i1++) /* different from your code */ 
    { 
     ... 
    } 
    ... 
} 

을 그렇지 않으면, 당신은 단지 s1을 제거하는 것이 더 낫다 Potatoswatter 같은 함수 정의에서 언급 한 :

long getMaxStart(long start, long count, ...) { 
    ... 
    va_start(marker, count); /* not a bug */ 
    maxstart = -1; /* pick something resonable for your app */ 
    for (i1 = 0; i1 < count; i1++) 
    { 
     ... 
    } 
    ... 
} 
+0

@karnastan : 명쾌한 설명에 +1 – morpheous

1

s1이 사용되지 않는다고 조금 의심 스럽습니다. counts1이 포함되어 있습니까? 즉, 전달 된 포인터의 총 개수는? 아마도 s1을 제거하고 va_start(marker, count)을 사용하고 싶을 것입니다.

편집 : 주석의 설명을 감안할 때이 수정 확실히

long getMaxStart(long start, long count, /* const myStruct *s1, */ ...) 
{ 
    long  i1, maxstart; 
    myStruct *s2; 
    va_list marker; 

    maxstart = start; 

    va_start(marker, count); 

    for (i1 = 1; i1 <= count; i1++) 
    { 
     s2 = va_arg(marker, myStruct *); 
     maxstart = MAX(maxstart, s2->firstvalid); 
    } 

    va_end(marker); 
    return (maxstart); 
} 

레거시 코드 ...이 무엇을 의미하는지 명확히 s1을 사용하지만 가변 인자의 작동을 방해하기 때문에, 당신이 필요하다 그것을 주석으로 처리하십시오.

+0

s1 IS가 사용되었습니다 - 함수 정의에서 다섯 번째 명령문입니다. – morpheous

+0

이전 코드는 실제로 va_start (마커, 카운트)를 사용했습니다.이 코드는 변경되었습니다 (주석 처리되었습니다). 컴파일러는 va_start() 매크로의 두 번째 인수가 알려진 목록의 마지막 항목이 아니라는 경고를 받았습니다.이를 수정했습니다. – morpheous

+0

@morpheous :'s1'은'va_start'에 의해 플레이스 홀더로 "사용"되지만 그 내용은 버려집니다. 'va_start'에 전달하는 것이 아니라's1'의 선언을 지움으로써 컴파일러 경고를 제거하십시오. – Potatoswatter

0

va_startva_list 인수와 가변 인수를 시작하기 직전에 마지막 인수를합니다. 에 지정한 것 다음에 첫 번째 인수를 가져 오거나 va_arg을 이전 호출 한 후 다음 인수를 얻으려면 va_arg으로 호출합니다. 귀하의 경우에는 s1이 가변 인수 이전의 마지막 인수가 va_start(marker, s1)이므로 va_arg을 호출하면 함수 호출에 4th 인수를 얻으려고 시도하지만 4 번째 인수가 없으므로 이상한 행동을 취하십시오.

count 인수에 1을 입력하면 인수가 충분하지 않아도 루프에 계속 입력되기 때문에 조기에 va_arg을 호출합니다.이 작업을 수행 할 경우, 값 s1는 사용되지 않습니다,

for (i1 = 1; i1 < count; i1++) 

그러나 : 당신은 사용해야합니다. Karmastan의 대답과 함께하십시오.

관련 문제