在现有变量上调用malloc时会发生什么?

时间:2016-05-19 06:37:59

标签: c memory-management

如果某个变量过去已经malloc,那么如果再次呼叫realloc而不是malloc,会发生什么?它会导致内存泄漏吗?

我想知道,以便我可以在void memtest(char **foo) { if ( foo ) *foo = malloc(10); // Assuming *foo was already allocated in the past. } 调用传递给函数的参数之前添加检查,以避免潜在的泄漏。

void memtest(char **foo)
{
        if ( foo ) {
                if ( *foo ) {
                        free(*foo);

                        *foo = NULL;
                }

                *foo = malloc(10);
        }
}

我是否应该始终执行以下操作?

- (void)deleteDialogWithID:(NSString *)dialogId completion:(void (^)(QBResponse *))completion {

    NSParameterAssert(dialogId);

    __weak __typeof(self)weakSelf = self;

    [QBRequest deleteDialogsWithIDs:[NSSet setWithObject:dialogId] forAllUsers:NO successBlock:^(QBResponse *response, NSArray *deletedObjectsIDs, NSArray *notFoundObjectsIDs, NSArray *wrongPermissionsObjectsIDs) {
        //
        [weakSelf.dialogsMemoryStorage deleteChatDialogWithID:dialogId];
        [weakSelf.messagesMemoryStorage deleteMessagesWithDialogID:dialogId];

        if ([weakSelf.multicastDelegate respondsToSelector:@selector(chatService:didDeleteChatDialogWithIDFromMemoryStorage:)]) {
            [weakSelf.multicastDelegate chatService:weakSelf didDeleteChatDialogWithIDFromMemoryStorage:dialogId];
        }

        [weakSelf.loadedAllMessages removeObjectsForKeys:deletedObjectsIDs];

        if (completion) {
            completion(response);
        }
    } errorBlock:^(QBResponse *response) {
        //
        if (response.status == QBResponseStatusCodeNotFound || response.status == 403) {
            [weakSelf.dialogsMemoryStorage deleteChatDialogWithID:dialogId];

            if ([weakSelf.multicastDelegate respondsToSelector:@selector(chatService:didDeleteChatDialogWithIDFromMemoryStorage:)]) {
                [weakSelf.multicastDelegate chatService:weakSelf didDeleteChatDialogWithIDFromMemoryStorage:dialogId];
            }
        }
        else {

            [weakSelf.serviceManager handleErrorResponse:response];
        }

        if (completion) {
            completion(response);
        }
    }];
}

5 个答案:

答案 0 :(得分:5)

如果*foo的指针包含指向先前分配的内存的唯一指针,那么您刚刚泄漏了之前的内存。否则,它是完全无害的。

答案 1 :(得分:5)

malloc的调用无关紧要。

如果出现问题,问题就在于作业。完成x=42;之后x的前一个值已经消失,无论它有多重要。同样,如果foo是唯一指向某个内存的指针,如果覆盖foo,则无法再访问该内存。

如果没有指定要释放的内容,则无法致电free。因此,如果你在丢失唯一指针之前没有释放内存,那么你就无法释放它,这就是内存泄漏的定义。

答案 2 :(得分:5)

没有“在变量上调用malloc”。

malloc找到一些“空闲”内存,将其标记为“已使用”,并返回刚刚找到的内存开头的地址。 free将某些“已使用”的内存标记为“免费”。

运行时

*foo = malloc(10);

发生以下情况:

  • malloc找到10个字节的可用内存。
  • malloc标记使用的那10个字节。
  • malloc返回刚刚找到的10个字节的开头地址。
  • 您的程序会查看foo的值,这是一个地址,因为foo是指针。
  • 您的程序将返回的地址malloc存储在foo中存储的地址。

malloc无关心你的程序对它返回的地址的处理方式。它不关心您的程序是将它存储在一个简单的变量,一个数组,另一个malloc ed空间,还是将它写入文件。它甚至不关心你的程序是否忘记了地址,但你应该关心,因为如果程序不知道它试图释放的内存的地址,你的程序将永远无法调用free。 p>

鉴于这些知识,你应该能够看到这段代码的作用:

char *bar;
bar = malloc(10);
bar = malloc(10);
free(bar);

花点时间弄明白,然后阅读以下内容:

  • 声明了一个名为bar的变量。其类型为char*
  • 该程序调用{​​{1}}。
  • malloc找到10个空闲字节并将其标记为已使用。
  • malloc返回10个字节的开头地址。
  • 程序将地址存储在malloc中。 (bar现在包含前10个字节的地址)
  • 该程序调用{​​{1}}。
  • bar找到10个可用字节,并将其标记为已使用。
  • malloc返回10个字节的开头地址。
  • 程序将地址存储在malloc中。 (malloc现在包含第二个10字节的地址)
  • 程序调用{​​{1}}并传递第二个10字节开头的地址。
  • bar将后10个字节标记为空闲。

这是内存泄漏。永远不会释放前10个字节。我可以告诉他们永远不会被释放,因为程序不知道他们在哪个地址。

但是这个节目怎么样?

bar

在这里,我在“已经保存了free个地址的变量上调用了free”。这是内存泄漏吗?不是单独的。该程序可能仍然是char *bar; char *baz; bar = malloc(10); baz = bar; baz = malloc(10); 第一个内存块,其地址仍存储在malloc中。

但是,这肯定是内存泄漏:

malloc

我甚至没有改变代码,只是把它放在一个函数中,它现在是内存泄漏! Whaaaaaaaaa?

记住内存泄漏究竟是什么。内存泄漏是指程序分配内存但从不释放内存。您无法通过查看free调用来判断程序是否释放了所有内存。

至于第二部分 - “我应该这样做吗?”

,你不应该。

仅当传递给您的函数的地址的旧值是baz ed指针,,如果调用者忘记void func() { char *bar; char *baz; bar = malloc(10); baz = bar; baz = malloc(10); } 它时,它才会起作用。

您的建议将破坏以下任何功能:

malloc

总之:标题中的问题没有意义。检测内存泄漏并不像这样简单。而你想要做的是一个坏主意。

答案 3 :(得分:3)

导致内存泄漏,因为先前分配的内存未被任何变量引用而您丢失了其地址。

没有具体检查。您可以在声明时将指针设置为NULL,并在每次内存NULL时将其设置为free。然后,您可以在if (pointer == NULL)之前检查malloc

使用realloc可以避免内存泄漏问题,因为如果指针是空指针,realloc函数的行为类似于指定大小的malloc函数。但如果您的指针未声明设置为NULL,则可能会导致问题。

即:

int *foo = NULL;

void bar( void )
{
     foo = realloc(foo, 10*sizeof(int));
}

realloc的一个好或坏特征是它保留了你记忆的内容。

  

我是否应该始终执行以下操作?

void memtest(char **foo)
{
        if ( *foo )
                free(*foo);

        *foo = malloc(10);
}

不,你不应该因为free没有将指针设置为NULL,并且你的指针仍然具有已经free内存的值程序中断错误。 我的意思是,如果您在代码中某处free指针而不重新分配它,则此类代码容易出错。 并且您必须确保将指针声明为NULL作为初始值。

答案 4 :(得分:1)

  

在现有变量上调用malloc会发生什么?

几乎没有可能:

  • 如果前一个malloc成功分配了内存,则重新分配内存将导致内存泄漏。
  • 如果以前malloc调用的内存分配失败,那么就不会有内存泄漏。
  

我是否应该始终执行以下操作?

void memtest(char **foo)
{
        if ( *foo )
                free(*foo); 
        *foo = malloc(10);
} 

是。通过这种方式,您可以确保没有内存泄漏。