malloc/free,似乎获得了多次释放

发布于 2024-11-17 13:17:11 字数 1030 浏览 9 评论 0原文

我编写了一个函数来测试给定路径是否是有效的 Maildir 目录(标准 Maildir 具有三个子文件夹 "cur" "new" 和 "tmp" )。函数接受假定的目录,检查这些子文件夹,然后正确返回。

我在当前代码的第二个自由语句中遇到了段错误,并且我同样遇到了“无效的下一个大小”错误,其组织略有不同。更令人困惑的是,它只在某些目录上出现段错误,而在其他目录上成功完成,没有明显的原因(尽管它在哪些目录上出现段错误是一致的)。注释掉第二个 free() 后,所有格式正确的目录都会成功完成。

显然我是双重释放的。我的问题是,为什么以及如何?如果第一个释放位于条件语句内,并且我们在释放后立即返回,则永远不会到达第二个释放。如果我们得到第二个免费的,这意味着我们跳过了第一个......对吧?

我意识到在这种情况下它完全没问题,因为系统将在程序结束时回收内存,但我对发生这种情况的原因更感兴趣,而不是仅仅让代码工作。如果我正在考虑不同的情况,函数由函数调用的函数等调用,并且内存可能是一个问题,该怎么办?我不需要第二个空闲来回收内存吗?

int is_valid_folder(char* maildir)
{
 struct stat *buf;
 buf = (struct stat *) malloc(sizeof(struct stat));

char* new = strdup(maildir);
char* cur = strdup(maildir);
char* tmp = strdup(maildir);
strcat (cur, "/cur"); strcat (new, "/new"); strcat (tmp, "/tmp");

if(stat(cur, buf) || stat(tmp, buf) || stat(new, buf))
{
printf("Problem stat-ing one of the cur/new/tmp folders\n");
printf("Error number %d\n", errno);
free(buf);
return 1;
}

free(buf);
return 0; //a valid folder path for this function
}

I've written a function to test if a given path is a valid Maildir directory (standard Maildir has the three subfolders "cur" "new" and "tmp" ). Function takes in the supposed directory, checks for those subfolders, and returns appropriately.

I'm getting a segfault at the second free statement with the current code, and I similarly got an "invalid next size" error with code of slightly different organization. Even more confusing, it only segfaults on some directories, while successfully completing on others, with no discernible reason (though it is consistent on which ones it will segfault on). With the second free() commented out, all accurately-formatted directories complete successfully.

Obviously I'm double-freeing. My question is, why and how? If the first free is inside the conditional statement and we return immediately after freeing, we never get to the second free. If we get to the second free, that means we skipped the first one... right?

I realize in this context it's perfectly fine because the system will reclaim the memory at the end of the program, but I'm more interested in the reason this is happening than in just making the code work. What if I were looking at a different situation, functions called by functions called by functions etc. and memory could possibly be a concern? Don't I need that 2nd free to reclaim memory?

int is_valid_folder(char* maildir)
{
 struct stat *buf;
 buf = (struct stat *) malloc(sizeof(struct stat));

char* new = strdup(maildir);
char* cur = strdup(maildir);
char* tmp = strdup(maildir);
strcat (cur, "/cur"); strcat (new, "/new"); strcat (tmp, "/tmp");

if(stat(cur, buf) || stat(tmp, buf) || stat(new, buf))
{
printf("Problem stat-ing one of the cur/new/tmp folders\n");
printf("Error number %d\n", errno);
free(buf);
return 1;
}

free(buf);
return 0; //a valid folder path for this function
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一念一轮回 2024-11-24 13:17:11

您有几个缓冲区溢出:strdup() 可能会分配一个 char 数组,该数组的大小刚好足以容纳 maildir 字符串,并且调用strcat() 将导致数组溢出。 (strcat()strdup() 不同,创建一个新的 char 数组,因此您必须确保您提供的数组足够大以容纳生成的字符串。)

顺便说一下,在跟踪内存管理方面,valgrind 是您的朋友错误。

You have several buffer overflows: strdup() probably allocates a char array that is just large enough to hold the maildir string, and the calls to strcat() will then overflow the arrays. (strcat(), as opposed to strdup(), does not create a new char array, so you must ensure yourself that the array you give it is large enough to hold the resulting string.)

By the way, valgrind is your friend when it comes to tracking down memory management bugs.

薄暮涼年 2024-11-24 13:17:11

重复字符串中没有足够的空间用于串联。

尝试:

char* new = (char*)calloc(strlen(maildir) + 5);

等等

There's not enough space in the duplicate strings for the concatenation.

try:

char* new = (char*)calloc(strlen(maildir) + 5);

etc

心欲静而疯不止 2024-11-24 13:17:11

我知道你明白了,但只是作为一个提示...(对于评论来说太大了)

检查 strdup() 的返回值是否为 NULLfree () 当您使用完这些指针后。如果你不这样做,内存就会泄漏(它在你当前的代码中泄漏)。

strdup() 函数应返回一个指向新字符串的指针,该字符串是 s1 指向的字符串的副本。 返回的指针可以传递给 free()。如果无法创建新字符串,则返回空指针。

I know you got it, but just as a tip... (too big for a comment)

Check the return value of strdup() for NULL and free() those pointers when you are done with them. If you don't memory will leak (it is leaking in your current code).

The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1. The returned pointer can be passed to free(). A null pointer is returned if the new string cannot be created.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文