2013-12-18 1 views
3

나는 몇 가지 다른 질문을 한 번 해봤지만 비슷한 문제는 해결하지 못했습니다.시간에 자유롭지 않는 기능

나는 (힙 정렬을 사용하여) 배열을 정렬하고 중앙값을 계산하는 기능을 가지고있다. 힙 정렬 루틴은 Numerical Recipies에서 직접 가져 왔습니다.

나는 중간 값 함수 안에 배열을 가지고 있지만, 시간 공간을 비우지 않는 것 같습니다. 여기에 내가 무엇을 의미하는지 설명하는 몇 가지 코드는 다음과 같습니다

int calcMedian(int n1, int n2, int *dat) 
{ 
    int ii, npt; 
    int *inparr, retval; 

    npt = n2 - n1 + 1; /* Number of elements in array */ 
    inparr = calloc(npt+1, sizeof(*inparr)); 

    for(ii = n1; ii <= n2; ii++) 
     inparr[ii-n1+1] = dat[ii]; /* ii-n1+1 because heapsort function likes arrays to 
           start from 1 */ 

    heapsortInt(npt, inparr); /* The error isn't here, function has been previously 
           debugged. Sorting is in-place.*/ 
    if (npt % 2) 
     retval = inparr[(npt+1)/2]; 
    else 
     retval = (inparr[npt/2]+inparr[npt/2+1])/2; 

    free(inparr); 
    return(retval); 
} 

기능 heapsortInt은 아주 철저하게 디버깅되었으며 문제없이 여러 가지 다른 장소에서 사용되고있다. 지금은과 같이 루프 내 기능 calcMedian 전화 : 그래서 기본적으로 calcMedian와 점점로 하나 개의 큰 배열의 다른 섹션을 통과하고있어

int *data1, *data2; 
int *npt1, *npt2; 

data1 = calloc(maxval * maxpt, sizeof(*data1)); 
data2 = calloc(maxval * maxpt, sizeof(*data2)); 

npt1 = calloc(maxval, sizeof(*npt1)); 
npt2 = calloc(maxval, sizeof(*npt2)); 

: 관련 변수가 아래에 정의되어

for(ii = 0; ii < maxval; ii++) { 
    index = ii * maxpt; 
    med1 = calcMedian(index, index+npt1[ii]-1, data1+index); 
    med2 = calcMedian(index, index+npt2[ii]-1, data2+index); 
} 

필요한 중앙값을 다시 계산하십시오.

문제 :calcMedian이 두 번째 함수 호출에 부딪 힐 때 충돌이 발생하는 것으로 보입니다. 나는 Valgrind의를 통해 실행,이는 나에게 말했다 것입니다 :

Invalid read of size 4 
at 0x43F67E: calcMedian /* Line no. pointing to calloc in calcMedian */ 
by 0x4416C9: main /* Line no pointing to second call of calcMedian */ 
Address 0x128ffdc0 is 6,128 bytes inside a block of size 110,788 free'd 
at 0x4A063F0: free 
by 0x43F728: calcMedian /* Line no. pointing to free in calcMedian */ 
by 0x4416C9: main /* Line no pointing to first call of calcMedian */ 

이이 free에 문제가 있습니까? freecalloc이 너무 자주 전송됩니까? 디버깅을 시작할 위치를 모르겠습니다. 어떤 도움도 훌륭합니다!

면책 조항 : 실제 코드가있는 컴퓨터는 인터넷에 액세스 할 수 없습니다. 문제의 원인이되는 코드를 정확히 여기에서 재현했습니다. 세미콜론이 누락 된 경우 등 그것이 내 잘못 인 경우 원래 코드에없는 것입니다.

편집 : 일부 필사적 오류가 수정되었습니다. 최대한 빨리 원본 코드를 얻으려고 시도 할 것이지만, 지금부터는이 두 가지를 모두 살펴 보는 것으로부터 이것은 괜찮을 것 같습니다.

+1

'free' 항상 "시간에"해제합니다. 진정한 [SSCCE] (http://sscce.org)가 없으면 여기서 구체적인 조언을 드리기가 어렵습니다. –

+2

문제는 범위 밖의 색인입니다. 'index + npt1 [ii] -1' 또는 다른 가능성이 유효한 메모리 주소를 계산할 가능성이 있습니다. 그러나 최근에는 해제 된 메모리를 가리 킵니다. 부가 메모 : 배열이 할당 된 범위를 초과하여 지속되어야하거나 배열이 여러 메가 바이트가 아닌 경우를 제외하고는'calloc' 대신 스택 배열을 사용하십시오. –

+0

메모리를 망칠 수도 있습니다. 메타 데이터가 손상되면'free' 또한 신뢰할 수 없게 될 수도 있습니다. – Devolus

답변

3

문제는 calcMedian을 호출하는 것입니다.

색인을 두 번 추가합니다. 한 번 호출 한 다음 calcMedian을 추가합니다.

그것은 다음과 같이해야한다 :

med1 = calcMedian(index, index+npt1[ii]-1, data1); 
med2 = calcMedian(index, index+npt2[ii]-1, data2); 
+0

합리적인 것 같습니다. 그래서 나머지 질문은 Valgrind가 (결과적으로) 결과적으로 한계를 벗어난 액세스를보고하지 않는 이유는 무엇입니까? 아, 그리고 오류보고가 어떻게 나오고 *보고되고 있습니까? –

+1

젠장, 그게 다야! 나는 바보처럼 느껴진다. 모든 도움을 주셔서 감사합니다! – Kitchi

+0

@OliCharlesworth - 저는 어떤 일이 일어나고 있는지 생각해 봅니다. 왜냐하면 초기 색인이 지나가고 있기 때문에 배열은 중간에 시작되어 배열이 범위를 벗어난 후에 오류를보고하기 때문입니다. 그래서 나는'calcMedian' 루프의 절반 만 보았습니다. – Kitchi