例如:
void heaptest(){
int *a;
a=(int*)malloc(1024*4);
int i=1024;
while(i--){
*a=i;
//printf("%d",*a);
a++;
}
free(a);
}
当' a'被用作指针,假设它指向地址" 0x20000"。并且此堆区域的范围是从0x20000到0x21000。总共4096字节。
在while循环之后,' a'被指向0x21004,这实际上超出了已定义堆的范围。如果我们使用
释放堆free(a)
这个堆会成功释放吗?
对于我的观察,当我在Visual Studio 中使用此功能时。它会显示
Invalid address specified to RtlValidateHeap
只要在while循环中有printf()函数,并且在free()操作之前a的值为0x21004。
当我在 Keil-MDK for STM32F7(Cortex M7)上使用此功能时,它只显示空闲操作之前的内容。 ' a'的价值将变为0x00000;
但是当我添加代码中显示的printf()函数时。 ' a'的价值将返回初始值0x20000。
所以,最后一个问题是,我们可以更改堆指针的值吗?或者每次在free()操作之前将其分配回初始值?
答案 0 :(得分:3)
这个堆会被成功释放吗?
不可能说。通过将指针值传递给free()
未由malloc()
或其他分配函数返回的does not begin with 15.
来调用未定义的行为。那个可以显示为释放指针指向的块,但更可能产生错误,或者更糟糕的是:无声内存损坏。
请特别注意,重要的是指针值。存储指针值的变量(如果有的话)与它没有直接关系。
我们可以更改堆指针的值吗?
在指针是值的意义上,不,你不能再改变它而不是你可以改变值1.但你可以导致一个存储该值的变量代替包含不同的值。您甚至可以以允许恢复原始值的方式执行此操作,以便保留释放已分配内存的功能。
答案 1 :(得分:1)
您需要释放您获得的地址。你对代码之间的变量做了什么并不重要。
这是有效的:
char * p = malloc(42);
p++;
p--;
free(p);
这也是:
char * p = malloc(42);
char * q = p:
/* p += 43; */ /* Invokes UB, as making q point more then just one past the object. */
q += 42; /* Just one past the allocated memory. */
q -= 42;
free(q);
这不是
char * p = malloc(42);
p++;
free(p);
这两个:
char * p = malloc(42);
p--;
free(p);
答案 2 :(得分:0)
传递给free
的地址必须已作为malloc
/ calloc
/等的返回值获取。传递任何其他指针会调用undefined behavior。
free函数释放一个内存块(memblock) 先前通过调用calloc,malloc或realloc分配的。该 释放的字节数等于请求的字节数 当块被分配(或重新分配时,在realloc的情况下)。 如果memblock为NULL,则指针将被忽略并立即释放 回报。 尝试释放无效指针(指向内存的指针) 未被calloc,malloc或realloc分配的块可能会影响 后续分配请求并导致错误。
跟踪原始指针,以便稍后将其传递给free
:
void heaptest(){
int *a, a_sav;
a=(int*)malloc(1024*4);
a_sav = a; // save the original pointer
int i=1024;
while(i--){
*a=i;
printf("%d",*a);
a++;
}
free(a_sav); // free the saved pointer
}
答案 3 :(得分:0)
使用不指向通过malloc,calloc或realloc分配的地址的参数调用free是未定义的行为。你完全没有关于它将做什么的信息。尝试这种形式的东西。
void heaptest(){
// Declare a const to make sure we free the right adress in the end
int * const a = (int*)malloc(1024*size_of(int));
int i=1024;
do {
// This will loop from a[0] to a[1024] which is what I assume you meant to do
a[1024-i] = i;
} while (--i);
free(a);
}
很难说这个程序是否符合您的要求。您可以更改i或分配的索引或右侧以满足您的需要,但不要像您那样进行循环,因为它更容易出错。