简体   繁体   English

free()函数在几次记忆之后导致崩溃

[英]free() function causes crash after several memmove's

I am writing a function acting like the splice function in js:given an array (of any type), delete some element starting at a given index, and stuff some new element in the gap (expand or shirnk the original array if needed). 我正在编写一个函数,其功能类似于js中的splice函数:给定一个数组(任何类型),删除从给定索引处开始的一些元素,并在间隙中填充一些新元素(如果需要,扩展或缩小原始数组)。

I am using MinGw/Eclipse CDT under Windows7. 我在Windows7下使用MinGw / Eclipse CDT。 Here is my code: 这是我的代码:

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;
}

and I also write some test code, the snippet below is for long long type: 并且我还编写了一些测试代码,下面的代码段适用于long long类型:

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;
}

It should output 7, 111,233 and 377 (delete six elements from index 1 and stuff 111,233 and 377 into the array). 它应该输出7、111,233和377(从索引1中删除六个元素,并将111,233和377填充到数组中)。

I tested for char, int, and long type arrays and under all situations the code worked. 我测试了char,int和long类型的数组,并且在所有情况下代码都可以正常工作。 Except for one problem:I cannot free the old array. 除了一个问题:我无法释放旧阵列。 It seemes that the memory block cannot be reclaimed once it has been accessed several times by memmove . 似乎一旦memmove对其进行了多次访问,便无法回收该内存块。

If I change malloc to realloc at (1) and the free() won't crash, but I can no longer make the function work right (And I am not sure whether the free() function really worked or not). 如果我将malloc更改为在(1)处重新分配,并且free()不会崩溃,但是我不能再使该函数正常工作了(而且我不确定free()函数是否真正起作用)。

Please give some advices about how this problem arise and how can I improve my code. 请提供一些有关此问题如何产生以及如何改进代码的建议。

Look at this line: 看这行:

    memmove(ptr,arr,typesize*size);

It tries to move typesize * size bytes to ptr. 它尝试将typesize * size个字节移动到ptr。 But you only allocated typesize*(size - gap) bytes. 但是您只分配了typesize *(size-gap)个字节。 That will lead to a crash if gap > 0 unless you are very unlucky. 如果gap> 0,将导致崩溃,除非您非常不幸。

I stopped checking after the first bug I found, so there may be more, and I didn't bother finding out what the code does. 在发现第一个错误之后,我停止了检查,因此可能还有更多错误,而且我也没有费心找出代码的作用。 You should add a comment which describes what the function should do well enough so that I could implement it without guessing or asking you questions. 您应该添加一条注释,其中描述了该功能应该做什么,以便我可以在不猜测或不问您的情况下实现该功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM