简体   繁体   English

释放指针会释放它引用的内存吗?

[英]Does Freeing a Pointer Free the Memory it References?

I'm currently working through Zed Shaw's Learn C the Hard Way tutorials and I'm trying to understand what is on the stack and what is on the heap in the following example, and how free() is working. 我目前正在阅读Zed Shaw的Learn C Hard Way教程,并且在下面的示例中,我试图了解堆栈中的内容和堆栈中的内容以及free()的工作方式。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

/** our old friend die from ex17. */
void die(const char *message)
{
    if(errno) {
        perror(message);
    } else { 
        printf("ERROR: %s\n",message);
    }
    exit(1);
}

// a typedef creates a fake type, 
// in this case for a function pointer
typedef int (*compare_cb)(int a, int b);
// by declaring this pointer to a function
// we can use this like an int/char etc. in a function's arguments
/**
* A classic bubble sort function that uses the
* compare_cb to do the sorting.
*/
int *bubble_sort(int *numbers, int count, compare_cb cmp)
{
    int temp = 0;
    int i = 0;
    int j = 0;
    int *target = malloc(count * sizeof(int));

    if(!target) die("Memory error.");

    memcpy(target, numbers, count * sizeof(int));

    for(i = 0; i < count; i++) {
        for(j = 0; j < count - 1; j++){
            if(cmp(target[j], target[j+1]) > 0) {
                temp = target[j+1];
                target[j+1] = target[j];
                target[j] = temp;

            }
        }
    }
    return target;  // returns address of target(I think)
}                   // target will persist even after function 
                    // exit because we created on the heap (memcopy)
                    // so what happens if we run more than once?

int sorted_order(int a, int b)
{
    return a - b;
}

int reverse_order(int a, int b)
{
    return b - a;
}

int strange_order(int a, int b)
{
    if(a == 0 || b == 0) {
        return 0;
    } else {
        return a % b;
    }
}

/** 
 * used to test that we are sorting things correctly
 * by doing the sort and printing it out.
 */
void test_sorting(int *numbers, int count, compare_cb cmp)
{
    int i = 0;
    int *sorted = bubble_sort(numbers, count, cmp);

    if(!sorted) die("failed to sort as requested.");

    for(i = 0; i < count; i++){
        printf("%d ", sorted[i]);
    }
    printf("\n");

    free(sorted);
    sorted = NULL; 
}

int main(int argc, char *argv[])
{
    if(argc < 2) die("USAGE: ex18 4 3 1 5 6");

    int count = argc - 1;
    int i = 0;
    char **inputs = argv + 1;

    int *numbers = malloc(count * sizeof(int));
    if(!numbers) die("Memory error.");

    for(i = 0; i < count; i++) {
        numbers[i] = atoi(inputs[i]);
    }
    test_sorting(numbers, count, sorted_order);
    test_sorting(numbers, count, reverse_order);
    test_sorting(numbers, count, strange_order);

    free(numbers);
    numbers = NULL;

    return 0;
}

In the function bubble_sort , an array of ints target is created on the heap. 在功能bubble_sort ,在堆上创建了一个ints target数组。 My understanding is that since this is on the heap, it will persist after the function exits. 我的理解是,由于这是在堆上,它将在函数退出后继续存在。

int *target = malloc(count * sizeof(int));

the function then returns target 函数然后返回target

return target;

I believe that means that the function returns the address of target 我相信这意味着该函数返回target 地址

later, in test_sorting the result of the bubble_sort function is passed 稍后,在test_sorting中通过bubble_sort函数的结果

int *sorted = bubble_sort(numbers, count, cmp);

so, if I'm right, the pointer sorted has been set to the same address as target 所以,如果我是对的,则sorted的指针已设置为与target相同的地址

at the end of test_sorting *sorted is freed but the data pointed to by *target is never freed. test_sorting *sorted被释放,但*target指向的数据从不释放。 But when I run the program in Valgrind I get no memory leaks, so this can't be true. 但是,当我在Valgrind中运行该程序时,没有内存泄漏,所以这不是真的。

Am I right, then, in saying that when I free a pointer, the thing it points to is freed? 我说对了,当我释放一个指针时,它指向的东西被释放了,对吗? I think probably not... I can't find any reference to this online so I'm assuming I'm mistaken at some point above, but I can't see where. 我想可能不是。。。我在网上找不到对此的任何参考,因此我假设我在上面的某个时候弄错了,但是我看不到哪里。

You're not running free to release the memory used to store the pointer value, but to free up the chunk of memory that pointer references, and the pointers sorted and target reference the same chunk of memory (within scope). 您不是在free运行以释放用于存储指针值的内存,而是释放指针所引用的内存块,并且sorted的指针和target引用同一块内存(在范围内)。 When you free that memory, neither pointer can be legally dereferenced to that chunk. free该内存时,任何指针都不能合法地取消引用该块。

Does Freeing a Pointer Free the Memory it References? 释放指针会释放它引用的内存吗?

Yes. 是。 Quoting from: Usage of free : 引用自: free

When we want to free a memory chunk previously allocated by malloc() , we use the free function. 当我们想要释放先前由malloc()分配的内存块时,我们使用free函数。 This function accepts a char pointer to a previously allocated memory chunk, and frees it - that is, adds it to the list of free memory chunks, that may be re-allocated. 该函数接受一个指向先前分配的内存块的char指针,并释放它-即,将其添加到可能重新分配的空闲内存块列表中。 Several notes about free() : 关于free()几点说明:

  • The size of the chunk was stored by malloc() previously in its memory map, and that is how free() knows how many bytes to free. 块的大小先前由malloc()存储在其内存映射中,这就是free()如何知道要释放多少字节的方式。
  • The freed memory is not being cleared or erased in any manner. 释放的内存不会以任何方式清除或擦除。 This is why accessing memory that was just freed often does not cause a crash - any data in it is still the same as before calling free() . 这就是为什么访问刚刚释放的内存通常不会导致崩溃的原因-内存中的任何数据仍然与调用free()之前的数据相同。

  • The free() function cannot nullify pointers to the given memory chunk that might still exist in our program. free()函数不能使指向仍可能存在于我们程序中的给定内存块的指针无效。 After we call free() , it is up to us (the programmers) not to try and dereference pointers that still point to that memory chunk. 在我们调用free() ,我们(程序员)应该决定不要尝试取消对仍然指向该内存块的指针的引用。 Such pointers are known as 'dangling pointers' - they point to memory that was already freed, and thus they should NOT be dereferenced again, unless they are assigned the address of a different (not-freed) memory chunk. 这样的指针称为“悬挂指针”-它们指向已经释放的内存,因此,除非为其分配了不同(未释放)内存块的地址,否则它们不应再次被取消引用。

As you can see, free() only marks the memory chunk as free - there is no enforcement of this freeing operation. 如您所见, free()仅将内存块标记为空闲-此释放操作没有强制执行。

The pointer itself is allocated on the stack and - as you already mentioned - holds an address. 指针本身已分配在堆栈上,并且-如您已经提到的-持有一个地址。 You also return the pointer by value and pass it by value unless you pass a pointer to the pointer. 您还按值返回指针并按值传递它,除非您将指针传递给该指针。 Malloc allocates memory somewhere and returns a pointer to this location(the address). Malloc在某处分配内存,并返回指向该位置(地址)的指针。 If you don't want this memory to become unusable, you have to tell the system that you don't need it any longer later. 如果您不希望此内存变得不可用,则必须告诉系统以后不再需要它。 Therefore you pass the address (ie the pointer) of the previously allocated chuck to free. 因此,您可以传递先前分配的卡盘的地址(即指针)释放。 This call actually frees the memory pointed to. 该调用实际上释放了指向的内存。 The pointer itself will go out of scope when the function returns. 函数返回时,指针本身将超出范围。

Yes, sorted and target will have the same address. 是的,排序和目标将具有相同的地址。
You can see this by printing both values. 您可以通过同时打印这两个值来查看。
In bubble_sort: printf("target address %X\\n", target); 在bubble_sort中:printf(“目标地址%X \\ n”,target);
In test_sorting: printf("sorted address %X\\n", sorted); 在test_sorting中:printf(“已排序地址%X \\ n”,已排序);

These should be the same, so the address is returned, then freed. 这些应该是相同的,所以地址被返回,然后被释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM