Функция free() вызывает сбой после нескольких операций memmove

Я пишу функцию, действующую как функция thesplice в js: при наличии массива (любого типа), удалить некоторый элемент, начинающийся с заданного индекса, и вставить новый элемент в пробел (расширить или уменьшить исходный массив, если это необходимо).

Я использую MinGw/Eclipse CDT под Windows7. Вот мой код:

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:

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 и вставить в массив 111 233 и 377).

Я тестировал массивы типов char, int и long, и во всех ситуациях код работал. Кроме одной проблемы: не могу освободить старый массив. Похоже, что блок памяти не может быть восстановлен после того, как к нему несколько раз обращался memmove.

Если я изменю malloc на realloc в (1), и free() не сработает, но я больше не смогу заставить функцию работать правильно (и я не уверен, действительно ли работала функция free() или нет).

Пожалуйста, дайте несколько советов о том, как возникает эта проблема и как я могу улучшить свой код.


person Chris    schedule 28.11.2014    source источник
comment
Если вы не можете освободить этот блок, он в основном говорит, что он поврежден, поэтому вы где-то выходите за границы массива.   -  person dev_null    schedule 28.11.2014
comment
Этот конкретный пример вызывает сбой для вас? Потому что у меня он работает нормально, и я не вижу ничего плохого. Если это действительно сбой, попробуйте закомментировать memove() по одному, чтобы увидеть, какой из них (если есть) вызывает это.   -  person uesp    schedule 28.11.2014


Ответы (1)


Посмотрите на эту строку:

    memmove(ptr,arr,typesize*size);

Он пытается переместить байты typesize * size в указатель. Но вы выделили только typesize*(size - gap) байты. Это приведет к сбою, если зазор > 0, если только вам не повезет.

Я перестал проверять после первой обнаруженной ошибки, так что могут быть и другие, и я не стал выяснять, что делает код. Вы должны добавить комментарий, описывающий, что функция должна делать достаточно хорошо, чтобы я мог реализовать ее, не догадываясь и не задавая вам вопросов.

person gnasher729    schedule 28.11.2014
comment
Спасибо, я отредактировал свой пост. На самом деле пробел может быть отрицательным числом. Функция предназначена для изменения массива: удалить какой-то элемент, начиная с индекса, и заполнить пробел элементом другого массива. Исходный массив расширяется или сжимается в зависимости от того, сколько элементов удалено и сколько новых элементов добавлено. - person Chris; 28.11.2014
comment
Спасибо, теперь программа работает хорошо. Проблема действительно связана с ошибкой, которую вы нашли. - person Chris; 01.12.2014