Curl: Как очистить сохраненные данные во время работы программы - PullRequest
2 голосов
/ 21 марта 2019

Я создал текстовую строку состояния программы на C, которая использует curl для подключения к погодному сайту, получения данных, получения правильной информации и отображения ее на панели.Эта часть программы работает отлично.Проблема заключается в том, что после успешного подключения программы к серверу, загрузки страницы и ее сохранения в памяти, а также после того, как я извлекаю данные о погоде и отображаю их, программа не освобождает загруженную память, поэтому для нее требуются дополнительные 15 МБram, чтобы запустить, пока я не закрою программу.

Это, кажется, происходит правильно, когда я выпускаю:

curl_easy_perform(curl);

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

У меня это отлично работает на С ++ без использования дополнительной памяти, но я еще не нашел код для C, который правильно очищает память.

Чтобы понять суть ситуации, я собираюсь использовать код, который фокусируется исключительно на рассматриваемой проблеме и имеет точно такую ​​же проблему.Это взято с этого сайта: https://curl.haxx.se/libcurl/c/getinmemory.html

Кроме того, я также попытался использовать этот код без удачи.Я подумал, может быть, если бы я просто сбросил данные, я мог бы по крайней мере проверить связь с сайтом и проверить, работает ли моя сеть, но он ЕЩЕ хранит 15 МБ памяти: https://curl.haxx.se/libcurl/c/simple.html

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

mycurl.c:

/*

  Compile with:
  gcc -O2 -Wall mycurl.c -o mycurl -L/usr/include/curl/lib -lcurl

  Courtesy of:
  https://curl.haxx.se/libcurl/c/getinmemory.html

*/

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

struct MemoryStruct {
  char *memory;
  size_t size;
};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;

  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(ptr == NULL) {
    /* out of memory! */ 
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }

  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;
  return realsize;
}

int main(void)
{
  CURL *curl;
  CURLcode res;

  struct MemoryStruct chunk;

  chunk.memory = malloc(1);
  chunk.size = 0; 

  curl_global_init(CURL_GLOBAL_ALL);

  curl = curl_easy_init();

  curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com/");
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
  curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");

  res = curl_easy_perform(curl);

/* check for errors */ 
  if(res != CURLE_OK) {
    fprintf(stderr, "curl_easy_perform() failed: %s\n",
            curl_easy_strerror(res));
    return 1;
  }

  printf("%lu bytes retrieved\n", (unsigned long)chunk.size);

  curl_easy_cleanup(curl);
  free(chunk.memory);
  curl_global_cleanup();

  /* Everything is all cleaned up, so the memory usage should be back to      normal at this point. */

  printf("Waiting 3 seconds... Watch to see if the memory levels change between now and when the program says 'Done!' If you see a change in memory, there is likely a leak.)\n");


  /* When the program shuts down, the memory is released, but it should release after we cleanup and before the program terminates. Lets give ourselves a few seconds to spot if this is the case. Make sure to have 'top' or 'htop' open and  */

  sleep(3); // top and htop default at 3 second intervals, so we need more than that to spot a change


  printf("\nDone!\nDid the memory change?\n");

  return 0;
}

Память никогда не очищается до завершения работы программывниз.Я хотел бы иметь возможность очистить эту память и повторно использовать команду curl.

Я уверен, что вы задаетесь вопросом, почему я использую 15Mb?

Код должен использоваться дляRaspberry Pi Zero, который ограничен 512 МБ оперативной памяти (не может быть обновлен), и я не хочу отдавать 15 МБ, если мне действительно это не нужно.В настоящее время я использую этот код на Raspberry Pi 3B +;хотя, у меня была эта проблема с curl в течение длительного времени, даже на других архитектурах (x86 / 64).

Хотелось бы, чтобы это было решено.Благодарю.:)


**** РЕДАКТИРОВАТЬ ****


Благодарим hlscalon за ссылку на ошибку и, насколько я вижу, нахождение причины.

apt install libcurl4-openssl-dev

Приведенный выше код в Debian удалит libcurl4-gnutls-dev и установит libcurl4-openssl-dev вместо него.Это исправило ситуацию.

Ниже приведен список сайтов до и после того, как я перешел на libcurl4-openssl-dev.Изменение потребления памяти на всех сайтах изменилось с 15 МБ до 1 МБ или менее.

Чтобы другие пользователи могли легко проверить, возможно ли это для них, я сохранил весь свой код тестирования, который можно быстро сократить& вставил и запустил:

//curl_easy_setopt(curl, CURLOPT_URL, "https://kernel.org"); // before +15Mb, after +1Mb
  //curl_easy_setopt(curl, CURLOPT_URL, "https://stackoverflow.com"); // before +15Mb, after +1Mb
  //curl_easy_setopt(curl, CURLOPT_URL, "https://blog.apastyle.org/"); // before +15Mb, after +1Mb
  //curl_easy_setopt(curl, CURLOPT_URL, "http://forums.debian.net"); // before +0Mb, after +1Mb
  //curl_easy_setopt(curl, CURLOPT_URL, "http://support.blog.com/create-a-blog/"); // before +0Mb, after +1Mb
  //curl_easy_setopt(curl, CURLOPT_URL, "http://blog.alz.org/"); // before +0Mb, after +0Mb

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

Считайте, что этот пост все еще открыт для ответов, касающихся исправления libcurl4-gnutls-dev.К сожалению, похоже, что это ошибка, которая существует уже пару лет, поэтому я не задерживаю дыхание.

...