2014-11-28 3 views
0

배열에 주어진 인덱스에서 시작하여 일부 요소를 지우고 새 요소를 gap (필요한 경우 원래 배열을 확장 또는 축소).여러 memmove의 후 free() 함수가 발생합니다.

Windows7에서 MinGw/Eclipse CDT를 사용하고 있습니다.

int main(){ 
    setbuf(stdout,NULL); 
    int start = 1; 
    int delete = 6; 
    long long* oldArray= malloc(sizeof(long long)*7); 
    long long* stuff = malloc(sizeof(long long)*3); 
    oldArray[0]=7LL; 
    oldArray[1]=8LL; 
    oldArray[2]=4LL; 
    oldArray[3]=1LL; 
    oldArray[4]=55LL; 
    oldArray[5]=67LL; 
    oldArray[6]=71LL; 
    stuff[0]=111LL; 
    stuff[1]=233LL; 
    stuff[2]=377LL; 
    int newsize = 7-(delete-3); 
    void* newArray = splice(sizeof(long long),oldArray,7,start,delete,stuff,3); 
    if(newArray){ 

     //------------crash happens here----------- 
     //free(oldArray); 
     //------------- 

     oldArray = newArray; 
     int i=0; 
     for(;i<newsize;i++){ 
      printf("%I64d\n",oldArray[i]); 
     } 
    } 
    return 0; 
} 

그것은 출력 7, 111,233 및 377 (인덱스 1에서 여섯 개 요소를 삭제해야합니다 :

void* splice(int typesize,void* arr, 
     int size,int start, int length, 
      void* stuff,int size2){ 
    //length is the number of elements to remove 
    //and size2 is the number of elements to fill in the gap 

    //so size-gap will be the size of the new array after the function 
    //when gap is a minus number, the array grows 
    //and when gap is a positive number, the array shrinks 
    int gap = length-size2; 
    void* ptr = malloc(typesize*(size-gap));//--------(1)-------- 
    if(ptr==NULL){ 
     puts("error"); 
     return NULL; 
    } 
    //now the ptr array is empty, copy the original array(arr) 
    //to the ptr until the 'start' index 
    memmove(ptr,arr,typesize*start); 

    //fill the new array 'stuff' into ptr starting from 
    //the index after 'start' 
    memmove(ptr+typesize*start,stuff,typesize*size2); 

    //and copy the rest of the original array (starting from 
    //the index start+length, which means starting from 'start' index 
    //and skip 'length' elements) into ptr 
    memmove(ptr+typesize*(start+size2),arr+typesize*(start+length), 
      typesize*(size-start-length)); 

    return ptr; 
} 

와 나는 또한 몇 가지 테스트 코드를 작성, 코드 조각 아래 long long 유형입니다 : 여기 내 코드입니다 어레이에 111,233과 377을 넣는다).

char, int 및 long 형식 배열을 테스트했으며 모든 상황에서 코드가 작동했습니다. 한 가지 문제를 제외하고는 : 저는 이전 배열을 해제 할 수 없습니다. memmove에 의해 여러 번 액세스 된 메모리 블록은 재생 될 수없는 것처럼 보입니다.

malloc을 (1)에서 realloc으로 변경하고 free()가 중단되지 않지만 더 이상 함수가 올바르게 작동하지 않을 수 있습니다. 그리고 free() 함수가 실제로 작동하는지 여부가 확실하지 않습니다.).

이 문제가 발생하는 방법에 대한 조언과 코드 개선 방법을 알려주십시오. 이 라인에서

+2

그 블록을 해제 할 수 없다면 기본적으로 손상되었다고 말하며 어딘가에서 배열 경계를 넘어 설 것입니다. –

+0

이 특수한 예는 충돌을 일으 킵니까? 그것은 저를 위해 잘 작동하고 나는 틀린 아무것도 볼 수 없기 때문에. 만약 충돌이 발생하면, 한 번에 하나씩'memove() '를 주석 처리하여 어느 것이 있는지를 확인하십시오. – uesp

답변

3

봐는 :

memmove(ptr,arr,typesize*size); 

는 ptr에하는 typesize * size 바이트를 이동하려고합니다. 그러나 typesize * (size - gap) 바이트 만 할당했습니다. 당신이 아주 운이 좋다면 gap> 0이라면 충돌로 이어질 것입니다.

내가 발견 한 첫 번째 버그가 확인 된 후 더 이상있을 수 있으므로 코드가하는 일을 파악하는 데 신경 쓰지 않았습니다. 추측하거나 질문하지 않고도 구현할 수 있도록 함수가 잘 수행해야하는 것을 설명하는 주석을 추가해야합니다.

+0

감사합니다, 나는 내 게시물을 편집했습니다. 사실 간격은 음수 일 수 있습니다.이 함수는 배열을 수정하는 것을 목표로합니다. 인덱스에서 시작하여 일부 요소를 삭제하고 다른 배열의 요소를 간격에 채 웁니다. 원래 배열은 제거되는 요소의 수와 새 요소의 수에 따라 확장되거나 축소됩니다. – Chris

+0

감사합니다. 지금은 프로그램이 잘 작동합니다. 문제는 발견 한 버그 때문입니다. – Chris