Вопрос

Я пишу приложение на C, используя Win32 API.Когда я пытаюсь увеличить размер моего массива с помощью функции HeapRealloc(), она меняет мои текущие значения в массиве, а не копирует их.Код, который я использую для перераспределения памяти:

BOOL ChangeFeedArraySize(UINT newSize)
{   
    char tempChar[20] = "";
    PFEED tempArr;
    if (newSize == 1)
    {
        tempArr = (PFEED)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(FEED));
    }
    else
    {
        tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, categoryArray, newSize * sizeof(FEED));
        // FEED - a struct
        // PFEED - a pointer to the struct
        // categoryArray - array to be reallocated
    }

    if (tempArr != NULL)
    {
        MessageBox(NULL, ltoa(HeapSize(heap, 0, tempArr),tempChar,10) , "Heap size after reallocation", MB_OK | MB_ICONEXCLAMATION);
        feedArray = tempArr;
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

Вот состояние массивов в точке останова.массив каналов показывает текущее состояние массива.временный массив показывает новое состояние перераспределенного массива (которое отличается).

массив подачи:

FeedArray http://www.freeimagehosting.net/uploads/526b0b2172.jpg

временный массив:

tempArray http://www.freeimagehosting.net/uploads/17858f2e7e.jpg

Пожалуйста помоги..:\

Ссылка на описание функции на MSDN

Это было полезно?

Решение

Вы ссылаетесь на специфичную для Windows функцию, но это справедливо и для realloc(), что является стандартным эквивалентом.

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

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

Как правило, шаблон, которому вы хотите следовать для подобных вещей, выглядит следующим образом:

void *newmem = realloc(oldmem, newsize);
if (!newmem)
{
   // TODO: handle failure
   // possibly free(oldmem); depending on how you want to handle errors
}
else
{
   oldmem = newmem;
}

Обычный ярлык, который используют люди: «oldmem = realloc(oldmem, newsize);", но это не так изящно, как вышеописанное, так как протекает oldmem когда есть неудача.

Обновление на основе вашего редактирования:

В вашем коде меня интересует одна вещь:

if (newSize == 1)
{
    tempArr = (PFEED)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(FEED));
}

Похоже, это предполагает, что первое распределение всегда будет иметь размер один.Ты уверен, что не хотел сказать if (feedArray == NULL), затем выделите newSize * sizeof(FEED)?

Второе обновление:

ХОРОШО.Еще одна вещь, которая выделяется, это:

    tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, категорияМассив,
                                 newSize * sizeof(FEED));
    // Snip...

    if (tempArr != NULL)
    {
        // Snip...
        FeedArray = tempArr;

Выделенные жирным шрифтом части должны быть одинаковыми.

Другие советы

Из документации я вижу, что:

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

Итак, следующий вопрос: как прийти к выводу, что содержимое массива изменилось?Не могли бы вы предоставить код?Вполне возможно, что могут возникнуть проблемы с указателями и/или предположения о том, куда теперь указывают существующие указатели (важно предположить, что вызов операционной системы корректен и полностью исчерпать любую возможность того, что код вашего приложения может быть ошибочным в первую очередь, потому что, хотя ошибки могут существовать при вызове операционной системы, вполне вероятно, что ошибка с такой важной функцией, как эта, была бы замечена раньше).

После вызова HeapReAlloc исходный CategoryArray был освобожден, и вы больше не владеете им.Другие распределения могли повторно использовать его для других целей, и содержимое могло измениться.С этого момента вам нужно использовать tempArr:

tempArr = (PFEED)HeapReAlloc(heap, HEAP_ZERO_MEMORY, categoryArray, newSize * sizeof(FEED)); 
cetagoryArray = tempArr;

где вы ищете вызов HeapRealloc?вам следует заглянуть в ВЕРНУЛСЯ указатель, а не исходный, который был им освобожден после вашего вызова

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top