Я создал текстовую строку состояния программы на 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.К сожалению, похоже, что это ошибка, которая существует уже пару лет, поэтому я не задерживаю дыхание.