释放动态分配的数组 C



我有点进退两难,因此,首先我想道歉,如果下一个问题会更菜鸟,或者他们之前被问过(我找不到答案)。

无论如何,我将以任务为例来解释它(这不是家庭作业,只是为了我的问题)。事情是这样的:

Given a string from stdin index each word, then print each word on one line.
Example:
str[] = "Stack is awesome"
str_index {
[0] => "Stack"
[1] => "is"
[2] => "awesome"
}

我知道有很多方法可以解决这个问题,但是,再次,为了我的问题

裸露此解决方案:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* fgets adds an unwanted 'n' at the end, so I made
* a special function to read from stdin that removes
* that 'n'.
*/
int read(char *str, int size) {
// fgets adds an unwanted 'n' at the end, so we remove it
fgets(str, size, stdin);
int length = strlen(str);
str[length - 1] = '';
return length;
}
/* A function that breaks a string into words, indexes them
* and prints them out, all done dynamically with malloc.
*/
void str_index(char *str) {
char **index, *ptr;
int i = 0, number_of_words;
index = malloc(sizeof(char *));
ptr = strtok(str, " ");
for(i = 0; ptr != NULL; i++) {
index = realloc(index, (i + 1) * sizeof(char *));
index[i] = malloc(50 * sizeof(char));
strcpy(index[i], ptr);
ptr = strtok(NULL, " ");
}
number_of_words = i;
for(i = 0; i < number_of_words; i++) {
printf("%sn", index[i]);
}
return;
}
int main() {
char str[250];
read(str, 250);
str_index(str);
return 0;

}

问题

  1. 我必须在何处释放动态分配的数组 在str_index?
  2. 我们是否必须在函数str_index中释放它们?如果是这样,为什么? 我所知道的是,当一个函数完成执行所有本地时 变量被销毁。
  3. 为什么我们必须释放它们?主要不是函数吗, 因此,在完成执行后,该函数中定义的所有变量都将被销毁。

我猜你正在上大学课程。大学课程的问题(在我看来)在于,他们从教授高级语言开始,一切都神奇地完成,然后教你低级语言。如果我统治世界,每个人都会从汇编程序开始,然后是C,然后被允许"进步"到Java等。

对于你的问题,你遇到的问题是假设"事情可能会神奇地完成"。C根本没有太多神奇的作用。特别是,如果您malloc()calloc()任何内容,或者使用使用堆分配器的东西(例如strdup())分配任何内容,则您有责任释放它。您将需要明确地执行此操作。如果不这样做,就会有内存泄漏。因此,第一个订单问题是"如果我分配了它,我必须确保它被释放"。第二个顺序问题是"如果我使用了一个可能已经分配了东西的库,我需要弄清楚如何确保它知道我已经做了,这样它就可以释放东西"。如果你记住这一点,你的C编程生活就会很幸福,valgrind将成为你的朋友。

现在让我们考虑您的问题:

  1. 您询问应该在哪里释放动态分配的内存。从技术上讲,在此示例中,您不需要这样做,因为退出程序将释放堆上的所有内存。但是,假设您想重复使用此函数。您希望在不再使用分配时立即释放分配。在给出的示例中,这将紧接在return之前。如果您有其他退出函数,请确保在每次return之前释放分配。一个有用的错误处理提示是通过相同的代码退出,并且每当free()分配时,还要将指向分配的指针设置为NULL。输入时,还要初始化指向NULL的指针。然后在退出时(goto的有效使用),您可以简单地检查指针是否NULL,如果它不为 null,则free()它。(事实上,一旦你变得非常自大,你就会知道free()在大多数平台上NULL是禁区,所以你可以无条件地释放它)。将指针设置为NULL位是为了避免双重释放。

  2. 这就是堆栈和堆之间的区别。局部变量在堆栈上分配。C 会在函数返回时自动销毁它们。这是C为数不多的魔术之一。请注意,我说过它破坏了变量,而不是它们指向的东西。因此,如果您在局部变量中有一个指向已分配(堆)内存的指针,并且该函数返回,它将"释放"变量(从某种意义上说,它将不再在堆栈上),但分配的(堆)内存不会被释放。这就是为什么您必须释放仅在函数中引用的堆分配内存,然后通过退出函数来销毁指向该函数的指针 - 请参阅上面 1 的答案。

  3. 在示例中,无需释放任何main()内容。如果您已将函数编码为返回指向堆上内存的指针(例如,如果您编写了等效的strdup()),那么您的main()函数将需要free()这一点。这就提出了一个重要的观点,即调用方需要free()的内容取决于被调用函数的设计方式。因此,被调用的函数在文档中使这一点显而易见是很重要的。

我必须在何处释放我在str_index中动态分配的数组?

就在函数的return;语句之前str_index.

我们是否必须在函数str_index中释放它们?

没必要。取决于程序要求。

我所知道的是,当一个函数完成执行时,所有局部变量都会被销毁。

是的,对于堆栈上分配的空间(如果变量未static),则适用于堆上分配的空间。

为什么我们必须释放它们?

没有必要freemain.取决于程序要求。

相关内容

  • 没有找到相关文章

最新更新