realloc(): недопустимый следующий размер

У меня проблема с функцией realloc. Я использую только C (поэтому без вектора) с LibCurl. Проблема, с которой я сталкиваюсь, заключается в том, что я получаю следующую ошибку (realloc(): недопустимый следующий размер) на 12-й итерации функции write_data (функция, которую я передаю Curl в качестве обратного вызова, она вызывается каждый раз, когда libcurl имеет некоторые данные для передачи обратно (данные передаются порциями) ).

След:

-Удаленный-

Источник:

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>

char * Data; //stores the data
size_t  RunningSize;

int write_data( char *ptr, size_t size, size_t nmemb, void *stream )
{
    size_t ThisSize = (size * nmemb); //Stores the size of the data to be stored
    size_t DataLen = strlen( Data ); //length of the data so far

    RunningSize = (RunningSize + ThisSize ); //update running size (used as new size)

   Data = realloc( Data, RunningSize ); //get new mem location (on the 12th iteration, this fails)
   strcat( Data, ptr); //add data in ptr to Data

    return ThisSize; //the function must return the size of the data it received so cURL knows things went ok.
}

int main( )
{
  CURL *curl;
  CURLcode res;
  const char * UserAgent = "";

  Data = malloc(1); //so realloc will work
  RunningSize += 1;

  curl = curl_easy_init();
  if(curl)
  {
    curl_easy_setopt( curl, CURLOPT_NOBODY, 0 );
    curl_easy_setopt( curl, CURLOPT_URL, "http://www.google.co.uk/" );
    curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt( curl, CURLOPT_USERAGENT, UserAgent );
    curl_easy_setopt( curl, CURLOPT_HEADER, 1 );

    //preform request.
    res = curl_easy_perform(curl);

    //output the data (debugging purposes)
    puts( Data );

    //cleanup
    curl_easy_cleanup(curl);
    free(Data);
  }

  return 0;
}

Заранее спасибо,


person Kewley    schedule 30.05.2010    source источник
comment
Не видя исходный код, трудно понять, что означает ваша таблица и что на самом деле происходит. Пожалуйста, укажите соответствующий исходный код в своем вопросе.   -  person CB Bailey    schedule 30.05.2010
comment
То, что вы разместили в pastebin, практически бесполезно. В вашем коде нет обращений к write_data, поэтому нет способа выяснить, что вы там делаете.   -  person AnT    schedule 30.05.2010
comment
@AndreyT: это обратный вызов, вызываемый из libcurl.   -  person Donal Fellows    schedule 30.05.2010
comment
В качестве примечания: нет необходимости делать malloc(1) для инициализации указателя на realloc. realloc может без проблем перераспределить нулевой указатель.   -  person AnT    schedule 30.05.2010
comment
realloc немного неудобно использовать правильно. Вам нужно убедиться, что это удалось, проверив возвращаемое значение, отличное от NULL, однако, если он действительно возвращает NULL, тогда память, на которую указывает параметр, все еще выделена, ее необходимо освободить. По этой причине не рекомендуется использовать x = realloc(x, n), если x — это всего лишь копия указателя на область памяти. Вам нужно сделать (что-то вроде) new_x = realloc(x, n); if (new_x) x = new_x; else failure_action();   -  person CB Bailey    schedule 30.05.2010
comment
Инициализация malloc(1) необходима для некоторых систем, таких как SUN OS 4.   -  person Joseph Quinsey    schedule 30.05.2010
comment
Не уверен, почему я использовал pastebin, если честно... Спасибо за комментарии и советы, я обязательно изменю свой код, чтобы проверить, возвращает ли realloc NULL. Спасибо!   -  person Kewley    schedule 01.06.2010


Ответы (1)


Данные, переданные в write_data(), не обязательно заканчиваются нулем; вот почему он сообщает вам количество байтов.

Это означает, что вы не можете использовать strcat(). Его использование приводит к выходу из конца массива и повреждению структур данных, используемых malloc/realloc, отсюда и ошибка.

Ваш write_data() должен вместо этого использовать memcpy(), например:

int write_data( char *ptr, size_t size, size_t nmemb, void *stream )
{
    size_t ThisSize = (size * nmemb); //Stores the size of the data to be stored
    size_t DataLen = RunningSize; //length of the data so far

    RunningSize = (RunningSize + ThisSize ); //update running size (used as new size)

    Data = realloc( Data, RunningSize ); //get new mem location (on the 12th iteration, this fails)
    memcpy((char *)Data + DataLen, ptr, ThisSize); //add data in ptr to Data

    return ThisSize; //the function must return the size of the data it received so cURL knows things went ok.
}

Вам также нужно будет инициализировать RunningSize значением 0, а не 1. Вы можете инициализировать Data значением NULL — допускается передача NULL значения realloc() (и оно ведет себя так же, как malloc()).

person caf    schedule 30.05.2010
comment
Большое спасибо за вашу помощь, это работает отлично! - person Kewley; 01.06.2010