【发布时间】:2022-08-16 08:27:30
【问题描述】:
我已经知道有no way 知道指针目标是否仍然是它的有效分配已经被释放,所以我试图使用指向指针的指针来解决这个问题,但它没有工作。
我的目标只是让print_block() 检测block 指针是否为无效的或不。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void free_block(u_int8_t **_block) {
// Dereference
u_int8_t *block = *_block;
// Info
printf(\"free_block()\\t-> %p Point To %p \\n\", &block, block);
// Free Block
free(block);
block = NULL;
}
void print_block(u_int8_t **_block) {
// Dereference
u_int8_t *block = *_block;
// Detectc if this block is freed
// This is the objective of this code
if(block == NULL) {
printf(\"print_block()\\t-> %p Is Null.\\n\", block);
return;
}
// Info
printf(\"print_block()\\t-> %p Point To %p -> \", &block, block);
// Print byte by byte
u_int8_t *p = block;
for(int i = 0; i < 3; i++) {
printf(\"0x%02X \", *(u_int8_t *)p);
p++;
}
printf(\"\\n\");
}
int main(void) {
// Allocat a block in the memory
u_int8_t *block = malloc(3 * sizeof(u_int8_t));
// Set all to zeros
memset(block, 0x00, 3);
// Info
printf(\"Main()\\t\\t\\t-> %p Point To %p \\n\", &block, block);
// Print the block content
print_block(&block);
// Free the block
free_block(&block);
// Print the block content gain
// This shold print Null because
// we freed the block.
print_block(&block);
return 0;
}
结果
Main() -> 0x7fffd549cc58 Point To 0xfa42a0
print_block() -> 0x7fffd549cc28 Point To 0xfa42a0 -> 0x00 0x00 0x00
free_block() -> 0x7fffd549cc60 Point To 0xfa42a0
print_block() -> 0x7fffd549cc28 Point To 0xfa42a0 -> 0xA4 0x0F 0x00
-
block = NULL;应该是*_block = NULL;。block = NULL;什么都不做,因为block即将超出范围。 -
此外,
printf(\"free_block()\\t-> %p Point To %p \\n\", &block, block);对于第一个参数&block实际上毫无价值。谁在乎局部变量的地址?这两个参数应该是_block和*_block。老实说,block在该功能中的用处根本值得商榷。 -
请注意,通常不应创建以下划线开头的函数、变量、标记或宏名称。 C11 §7.1.3 Reserved identifiers 的一部分说:-以下划线和大写字母或另一个下划线开头的所有标识符始终保留用于任何用途。—所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。另见What does double underscore (
__const) mean in C? -
你可以看看 Steve Maguire Writing Solid Code: 20th Anniversary 2nd Edn 2013。有些人非常不喜欢这本书;我认为它非常有用。它包括包装内存管理函数的代码,以便您可以跟踪给定指针是否仍然有效,并讨论了使用它的一些陷阱。值得注意的是,您必须安排包装任何分配内存的函数——例如
strdup()——并确保在代码中使用包装器。 -
你想解决什么问题,内存调试器还没有解决?