Перенос всех строк в массиве (проблема с realloc) - PullRequest
0 голосов
/ 08 апреля 2009

Я пытаюсь написать функцию, которая сдвигает все элементы в массиве строк на единицу.

void shift_frags(char **frags, int frag_len, int cur)
{
    int i;
    for(i = cur; i < frag_len-1; i++)
    {
        if(strlen(frags[i+1]) > strlen(frags[i]))
            frags[i] = realloc(frags[i], strlen(frags[i+1])*sizeof(char));
        strcpy(frags[i], frags[i+1]);
    }

    free(frags[frag_len-1]);
}

Это дает мне ошибку: "realloc (): неверный следующий размер: ..." Каждый массив динамически выделяется в соответствии с размером строки, читаемой из файла. Разве я не должен иметь возможность динамически выделять новые размеры массивов, так как мой параметр frags является массивом указателей?

Спасибо

Ответы [ 3 ]

3 голосов
/ 08 апреля 2009

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

Что-то приближающее это.

void shift_frags(char **frags, int frag_len, int cur)
{
  free(frags[frag_len]);
  memmove(frags+cur+1, frags+cur, (frag_len-cur) * sizeof(char*));
}
2 голосов
/ 08 апреля 2009

Нет необходимости free() / realloc().

Ваш char **frags является указателем на список указателей, так что вы можете просто перетасовывать значения указателя без создания новых строк.

Просто убедитесь, что вы начинаете с дальнего конца списка и считаете в обратном порядке, или используете memmove():

void shift_frags(char **frags, int frag_len, int cur)
{
    int i;

    free(frags[frag_len]); /* because otherwise this is left dangling */

    for(i = frag_len; i > cur; i--)
    {
        frags[i] = frags[i - 1];
    }
}

или

void shift_frags(char **frags, int frag_len, int cur)
{
    int n = frag_len - cur;
    frags += cur;
    free(frags[n]);
    memmove(frags + 1, frags, n * sizeof(*frags)); /* nb: memmove(dst, src, n) */
}

NB: здесь возможна ошибка «один за другим», это зависит от семантики вашего значения frag_len и от того, знаете ли вы, что блок памяти frag уже достаточно велик для размещения другого указателя.

1 голос
/ 08 апреля 2009

Вероятно, ваш realloc не работает, потому что вы не резервируете байт для завершающего символа NUL ('\ 0') в строках - добавляя +1 к размеру вашего realloc:

    if(strlen(frags[i+1]) > strlen(frags[i]))
        frags[i] = realloc(frags[i], (strlen(frags[i+1]) + 1)*sizeof(char));
    strcpy(frags[i], frags[i+1]);

исправит эту ошибку. Вероятно, конкретная ошибка возникает из-за того, что одна из ваших строк имеет длину 0, а realloc (foo, 0) просто выдает эту ошибку в вашей системе или потому, что вы записываете завершающий '\ 0' в нераспределенной памяти перезапись чего-то еще важного, что приводит к коррупции.

Простая перестановка указателей (frags [i] = frags [i + 1]) или использование memmove ()) проще, быстрее и, тем не менее, предотвращает потерю памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...