釋放指針是否釋放了它所引用的內存?

[英]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 the 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. My understanding is that since this is on the heap, it will persist after the function exits.

在函數bubble_sort中,在堆上創建一個int目標數組。我的理解是,由於這是在堆上,它將在函數退出后持續存在。

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

the function then returns target

然后該函數返回目標

return target;

I believe that means that the function returns the address of 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

所以,如果我是對的,已經排序的指針已設置為與目標相同的地址

at the end of test_sorting *sorted is freed but the data pointed to by *target is never freed. But when I run the program in Valgrind I get no memory leaks, so this can't be true.

在test_sorting結束時*已釋放,但* target指向的數據永遠不會被釋放。但是當我在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.

我是對的,然后說,當我釋放一個指針時,它指向的東西被釋放了嗎?我想可能不是......我在網上找不到任何參考,所以我假設我在某些方面錯了,但是我看不到哪里。

4 个解决方案

#1


2  

Does Freeing a Pointer Free the Memory it References?

釋放指針是否釋放了它所引用的內存?

Yes. Quoting from: Usage of free:

是。引用自由:免費使用:

When we want to free a memory chunk previously allocated by malloc(), we use the free function. 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. Several notes about free():

當我們想要釋放以前由malloc()分配的內存塊時,我們使用free函數。此函數接受指向先前分配的內存塊的char指針,並釋放它 - 即,將其添加到可以重新分配的空閑內存塊列表中。關於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. After we call free(), it is up to us (the programmers) not to try and dereference pointers that still point to that memory chunk. 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.

    free()函數不能使指向我們程序中可能仍然存在的給定內存塊的指針無效。在我們調用free()之后,由我們(程序員)決定不嘗試和取消引用仍然指向該內存塊的指針。這樣的指針被稱為“懸空指針” - 它們指向已經釋放的內存,因此它們不應再被取消引用,除非它們被分配了不同(未釋放)內存塊的地址。

As you can see, free() only marks the memory chunk as free - there is no enforcement of this freeing operation.

正如您所看到的,free()僅將內存塊標記為空閑 - 沒有強制執行此釋放操作。

#2


2  

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). When you free that memory, neither pointer can be legally dereferenced to that chunk.

你沒有自由釋放用於存儲指針值的內存,而是釋放指針引用的內存塊,並且指針排序和目標引用同一塊內存(在范圍內)。釋放該內存時,兩個指針都不能合法地取消引用該塊。

#3


1  

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). 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 (i.e. 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.

指針本身在堆棧上分配 - 正如您已經提到的 - 保存一個地址。您還可以按值返回指針並按值傳遞,除非您將指針傳遞給指針。 Malloc在某處分配內存並返回指向此位置的指針(地址)。如果您不希望此內存無法使用,則必須告訴系統您以后不再需要它。因此,您將先前分配的卡盤的地址(即指針)傳遞給空閑。這個調用實際上釋放了指向的內存。函數返回時,指針本身將超出范圍。

#4


0  

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);
In test_sorting: printf("sorted address %X\n", sorted);

是的,已排序和目標將具有相同的地址。您可以通過打印兩個值來查看。在bubble_sort:printf(“目標地址%X \ n”,目標);在test_sorting中:printf(“已排序的地址%X \ n”,已排序);

These should be the same, so the address is returned, then freed.

這些應該是相同的,所以返回地址,然后釋放。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/09/09/7212bcd20530c5084b992e74cca3d487.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com