我用C语言编写了一个文本状态栏程序,该程序使用curl连接到天气站点,获取数据,获取正确的信息并将其显示在栏中。该程序的这一部分工作完美。问题在于,在程序成功连接到服务器,下载页面并将其存储到内存之后,并且在提取天气数据并显示它之后,程序不会释放已下载的内存,因此需要额外的15Mb运行ram,直到我关闭程序。
这似乎是在我发出问题时发生的:
curl_easy_perform(curl);
我不知道如何在不关闭程序的情况下释放此内存,并且我需要程序保持打开状态。我不想创建一个单独的程序并调用它,因为将来我想在该程序中使用curl来实现其他功能(例如ping网络以检查连接),所以我也可能只要在它在那里就可以使用。
我已经在C ++中完美地完成了这一工作,没有占用额外的内存,但是我还没有找到正确清除内存的C代码。
为了深入了解情况,我将使用仅专注于当前问题且具有完全相同问题的代码。它取自本网站: https://curl.haxx.se/libcurl/c/getinmemory.html
顺便说一句,我也尝试过使用此代码,但没有运气。我以为也许我只是转储了数据,但我至少可以对一个站点执行ping操作,并检查我的网络是否正常运行,但是它仍然可以保留15Mb的内存: 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(仅限于512Mb ram(无法升级)),如果我真的不需要的话,我不想放弃15Mb。目前,我正在Raspberry Pi 3B +上运行此代码。但是,即使在其他体系结构(x86 / 64)上,我也有很长一段时间没有使用curl的问题。
很乐意解决它。谢谢。 :)
****编辑****
向hlscalon提供错误参考链接,并据我所知找出原因。
apt install libcurl4-openssl-dev
以上在Debian上的代码将卸载'libcurl4-gnutls-dev'并在其位置安装libcurl4-openssl-dev。这解决了这种情况。
以下是我切换到libcurl4-openssl-dev之前和之后的站点列表。在所有站点上,内存消耗的变化从15Mb变为1Mb或更小。
为了允许其他用户轻松测试是否适合他们,我保留了所有测试代码,可以快速将其剪切并粘贴并运行:
//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有关的答复。可悲的是,这似乎是已经存在了两年的错误,所以我没有屏住呼吸。