释放字符指针

发布于 2024-08-19 15:12:47 字数 334 浏览 3 评论 0原文

我有一个在程序执行期间被多次调用的函数。在上述函数中,我有一个动态字符指针,我多次调整其大小。

我的问题是:我需要在函数结束之前释放这个指针吗?

void functionName()
{
 char *variable = (char *) malloc(0);
    //variable is resized with realloc x number of times

 //should free be called here?
 return;
}

我还应该注意,我尝试释放指针,但是,当我这样做时,gdb 会发出警告。

I have a function which is called multiple times during the program's execution. In said function, I have a dynamic character pointer which I resize numerous times.

My question is: do I need to free this pointer before the end of the function?

void functionName()
{
 char *variable = (char *) malloc(0);
    //variable is resized with realloc x number of times

 //should free be called here?
 return;
}

I should also note that I have tried to free the pointer, however, gdb gives me warnings when I do so.

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

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

发布评论

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

评论(7

ゃ人海孤独症 2024-08-26 15:12:47

是的,你必须释放它,否则你会泄漏内存。您的代码应该如下所示:

void function(void) 
{
    char *variable = (char *)malloc(0);

    variable = realloc(variable, 10);
    // do something with new memory

    variable = realloc(variable, 20);
    // do something with more new memory

    free(variable);  // clean up
}

我认为调用 malloc(0) 有点奇怪。

Yes, you have to free it or you'll leak the memory. Your code should look something like this:

void function(void) 
{
    char *variable = (char *)malloc(0);

    variable = realloc(variable, 10);
    // do something with new memory

    variable = realloc(variable, 20);
    // do something with more new memory

    free(variable);  // clean up
}

Calling malloc(0) is a little weird, I think.

栖竹 2024-08-26 15:12:47

需要指出的几点:

我看不到你如何在代码中使用 realloc() ,但是如果你像这样使用它,那就错了:

variable = realloc(variable, amount);

当它无法分配更多内存时,< code>realloc() 返回 NULL 但保持原始指针不变。在上面的行中,这意味着 variableNULL 并且我们失去了对其指向的内存的访问权限,但该内存尚未被释放。正确的习惯用法是这样的:

void *tmp = realloc(variable, amount);
if(tmp)
  {
    // success! variable invalid, tmp has new allocated data
    variable = tmp;
  }
else
  {
    // failure! variable valid, but same size as before, handle error
  }

您应该使用第二个的原因是,使用 realloc() 时,失败是很糟糕的,但在许多情况下是可以恢复的,这与 malloc() 不同。 code> 其中失败通常意味着“停止一切并死亡”。

这是一个更有争议的问题,但是否应该像您一样转换 malloc()realloc() 的返回值是值得怀疑的。考虑一下:

// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);

在 C++ 中,必须进行强制转换,因为在 C++ 中,void * 无法隐式转换为其他指针类型。 (我认为这是一个语言错误,但这不是我判断的地方。)如果您的代码是 C++,那么您无论如何都应该使用 newdelete 。如果您的代码是 C 代码,但需要使用 C++ 编译器进行编译(由于某些愚蠢的原因),您别无选择,只能进行强制转换。如果您不需要使用 C++ 编译器编译 C 代码(这类似于必须在 Python 解释器中运行 Ruby 代码),请继续执行以下几点,这就是我认为您不应该进行强制转换的原因。

  1. 在 C89 中,如果在没有声明的情况下使用函数,它将被隐式声明为返回 int。比如说,如果我们忘记了#include并且调用了malloc(),那么没有强制转换的版本将导致编译器错误(从不允许将 int 转换为 char *),而带有强制转换的版本会(错误地)告诉编译器“我知道这听起来很疯狂,但无论如何都要强制转换它。”大多数编译器都会向您发出有关 malloc() 等内置函数的隐式(或不兼容)声明的警告,但强制转换确实会使查找变得更加困难。

  2. 假设您有一些数据:

    float *array = (float *)malloc(10 * sizeof(float));
    

    后来,您发现需要更精确的数据,并且必须将其设为 double 数组。在上面的行中,您需要更改的不同位置不超过 3 个:

    double *array = (double *)malloc(10 * sizeof(double));
    

    如果,另一方面,你写了:

    float *array = malloc(10 * sizeof *array);
    

    您只需将 1 个位置的 float 更改为 double 即可。此外,始终使用 sizeof *obj 而不是 sizeof(type) 并且从不使用强制转换意味着稍后调用 realloc() 可以工作< em>没有任何改变,而使用强制转换和显式类型名称则需要找到调用realloc的任何地方并更改强制转换和sizeof。另外,如果您忘记了,请执行以下操作:

    double *array = (float *)malloc(10 * sizeof(float));
    

    在大多数平台上,array 现在只是一个包含 5 个元素的数组,假设对齐未关闭并且编译器不会抱怨您正在分配 float *double *。有些人认为编译器发出的警告很有帮助,因为它指出了可能不正确的行。但是,如果我们避免 sizeof(type) 并避免强制转换,我们可以看到这些行不会不正确,因此让编译器注意它们是浪费时间我们可以用来编程。

A few points to make:

I can't see how you use realloc() in your code, but if you're using it like this, it's wrong:

variable = realloc(variable, amount);

When it's unable to allocate more memory, realloc() returns NULL but leaves the original pointer unaltered. In the above line, this means that variable is NULL and we've lost access to the memory it pointed to, but that memory hasn't been freed. The correct idiom is this:

void *tmp = realloc(variable, amount);
if(tmp)
  {
    // success! variable invalid, tmp has new allocated data
    variable = tmp;
  }
else
  {
    // failure! variable valid, but same size as before, handle error
  }

The reason you should use the second one is because, with realloc(), failure is bad, but is quite recoverable in many situations, unlike malloc() where failure usually means "stop everything and die."

This is a more contentious issue, but it is questionable whether or not you should cast the return value of malloc() and realloc() like you do. Consider:

// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);

In C++, the cast must be made, because in C++ void * cannot be implicitly converted to another pointer type. (I think this is a language mistake, but it's not my place to judge.) If your code is C++, you should be using new and delete anyway. If your code is C but needs to compile with C++ compilers (for some inane reason), you have no choice but to cast. If you don't need to compile C code with C++ compilers (which is similar to having to run Ruby code in a Python interpreter), continue to the points below, which are why I think you shouldn't cast.

  1. In C89, if a function is used without being declared, it will be implicitly declared as returning an int. If, say, we forgot to #include <stdlib.h> and we called malloc(), the version without a cast would cause a compiler error (implicit casts from int to char * aren't allowed), while the version with the cast would (wrongly) tell the compiler "I know this sounds crazy, but cast it anyway." Most compilers will give you a warning for implicit (or incompatable) declarations of built-in functions like malloc(), but the cast does make it harder to find.

  2. Say you have some data:

    float *array = (float *)malloc(10 * sizeof(float));
    

    Later, you discover that you need more precision on your data, and have to make this a double array. In the above line, you need to change no more than 3 different places:

    double *array = (double *)malloc(10 * sizeof(double));
    

    If, on the other hand, you had written:

    float *array = malloc(10 * sizeof *array);
    

    You would only need to change float to double in 1 place. Furthermore, always using sizeof *obj instead of sizeof(type) and never using casts means that a later call to realloc() can work without any changes, while using casts and explicit type names would require finding anywhere you called realloc and change the casts and sizeofs. Also, if you forget, and do this:

    double *array = (float *)malloc(10 * sizeof(float));
    

    On most platforms, array will now only be an array of 5 elements, assuming the alignment isn't off and the compiler doesn't complain that you're assigning a float * to a double *. Some consider the warning the compiler issues to be helpful, as it points out potentially incorrect lines. However, if we avoid sizeof(type) and avoid casting, we can see that the lines won't be incorrect, so having the compiler draw attention to them is wasting time we could be using to program.

贵在坚持 2024-08-26 15:12:47

从手册页来看:

如果 size 为 0,则 malloc() 返回 NULL,或者稍后可以成功传递给 free() 的唯一指针值。

所以,我相信答案是“是”:)。

From the man pages:

If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

So, I believe the answer is "yes" :).

江湖正好 2024-08-26 15:12:47

是的,您需要调用一次 free() 来释放内存块。您不需要为您正在执行的后续 reallocs() 调用 free,即使它们返回不同的地址/指针。内存管理器知道不再需要旧块并将其 free() 。

Yes you need to call free() once to release the block of memory. You do not need to call free for the subsequent reallocs() that you are doing, even if those return a different address/pointer. The memory manager knows that the old block is not needed any longer and will free() it.

灰色世界里的红玫瑰 2024-08-26 15:12:47

您应该能够在最后调用 free(variable) 。如果 realloc 必须移动数据才能调整其大小,它会在内部调用 free,您无需担心这一点。

另外,在初始化变量时,您可以将其设置为NULL,而不是调用mallocrealloc 将像第一次使用 malloc 一样工作。

You should be able to just call free(variable) at the end. If realloc ever has to move the data in order to resize it, it calls free internally, you do not need to worry about that.

Also, where you initialize variable, you could just set it to NULL instead of calling malloc; realloc will work just like malloc the first time.

[浮城] 2024-08-26 15:12:47

看看我对与内存管理相关的几个问题给出的一些答案:

以上所有内容都指出了显而易见的是,对于每个 malloc 都有一个空闲空间,如果没有,就会发生内存泄漏,因此当您使用完指针变量时,必须释放内存那就是mallocd。

希望这有帮助,
此致,
汤姆.

Have a look at some of the answers I have given to a couple of questions in relation to memory management:

All of the above point out the obvious thing, for every malloc there is a free, if not you have a memory leak, so it is imperative that you free the memory when you are finished with your pointer variable that is mallocd.

Hope this helps,
Best regards,
Tom.

2024-08-26 15:12:47
int main(int argc, char *argv[])
{
        char *p = malloc(sizeof(argv[1]));

        p = argv[1];
        printf("%s\n", p);
        free(p);
        return 0;
}

我收到 glibc 错误

hello
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96]
./a.out[0x4005ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]
int main(int argc, char *argv[])
{
        char *p = malloc(sizeof(argv[1]));

        p = argv[1];
        printf("%s\n", p);
        free(p);
        return 0;
}

iam getting the glibc error

hello
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96]
./a.out[0x4005ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文