我目前正在通过Zed Shaw的“学习硬困难教程”教程,我试图了解堆栈中的内容以及以下示例中的堆上的内容,以及如何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;
}
在函数bubble_sort
中,在堆上创建一个int target
数组。我的理解是,由于它在堆上,它将在函数退出后保持不变。
int *target = malloc(count * sizeof(int));
然后该函数返回target
return target;
我相信这意味着该函数返回target
的地址
稍后,在test_sorting
中传递bubble_sort
函数的结果
int *sorted = bubble_sort(numbers, count, cmp);
所以,如果我正确,指针sorted
已设置为与target
相同的地址
test_sorting
*sorted
末尾的被释放,但*target
指向的数据永远不会被释放。
但是当我在Valgrind运行程序时,我没有内存泄漏,所以这不可能。
我是对的,然后说,当我释放一个指针时,它指向的东西被释放了吗? 我想可能不是......我无法在网上找到任何参考资料,所以我假设我在上面的某个方面有误,但我无法看到。
答案 0 :(得分:2)
你没有运行free
来释放用于存储指针值的内存,而是释放指针引用的内存块,以及指针sorted
和target
引用相同的内存块(在范围内)。当你free
那个内存时,两个指针都不能合法地取消引用该块。
答案 1 :(得分:2)
释放指针是否释放了它所引用的内存?
是。引自:Usage of free
:
当我们想要释放先前由
malloc()
分配的内存块时,我们使用自由函数。此函数接受指向先前分配的内存块的char指针,并将其释放 - 即,将其添加到可以重新分配的可用内存块列表中。关于free()
的几点说明:
- 块的大小先前由
malloc()
存储在其内存映射中,这就是free()
知道要释放多少字节的方式。未以任何方式清除或删除释放的内存。这就是为什么访问刚刚释放的内存不会导致崩溃的原因 - 其中的任何数据仍然与调用
free()
之前的数据相同。free()函数无法使指向我们程序中可能仍然存在的给定内存块的指针无效。在我们调用
free()
之后,由我们(程序员)决定不尝试和取消引用仍然指向该内存块的指针。这样的指针被称为“悬挂指针”&#39; - 它们指向已经释放的内存,因此不应再次取消引用它们,除非它们被分配了不同(未释放)内存块的地址。
正如您所看到的,free()
仅将内存块标记为空闲 - 没有执行此释放操作。
答案 2 :(得分:1)
指针本身在堆栈上分配,并且 - 正如您已经提到的 - 保存一个地址。您还可以按值返回指针并按值传递,除非您将指针传递给指针。 Malloc在某处分配内存并返回指向此位置的指针(地址)。如果您不希望此内存无法使用,则必须告诉系统您以后不再需要它。因此,您将先前分配的卡盘的地址(即指针)传递给空闲。这个调用实际上释放了指向的内存。当函数返回时,指针本身将超出范围。
答案 3 :(得分:0)
是的,已排序且目标将具有相同的地址
您可以通过打印两个值来看到这一点
在bubble_sort:printf(&#34;目标地址%X \ n&#34;,目标);
在test_sorting中:printf(&#34;已排序的地址%X \ n&#34;,已排序);
这些应该是相同的,所以返回地址,然后释放。