我已經知道沒有辦法知道指標目標是否仍然是它的有效分配已經被釋放,所以我試圖使用指向指標的指標來解決這個問題,但它沒有用。
我的目標只是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("0xX ", *(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
uj5u.com熱心網友回復:
你可以使用Block
struct
一點點紀律。
舉個例子
typedef struct
{
size_t size;
uint8_t fill;
uint8_t* data;
} Block;
Block* free_block(Block*);
Block* get_block(size_t size, uint8_t fill_value);
void print_block(Block* block, const char* title);
和
- 使函式對指向的指標進行操作
Block
,封裝資料 - make
free_block()
returnNULL
以簡化使塊指標無效的任務 - 測驗里面的塊地址
print_block()
- 在中使用可選標題
print_block()
以主要為例
int main(void)
{
const int test_size = 32;
Block* block = get_block(test_size, 0); // zero-filled
printf(
"Main()\t\t\t-> Pointer at %p points to data at "
"%p\n",
&block, block->data);
print_block(block, "\nBlock contents:");
block = free_block(block);
print_block(block, "\nafter free()");
return 0;
}
也許您會發現這種方式更易于閱讀。
main 的輸出如上
Main() -> Pointer at 00CFF754 points to data at 00E96C70
Block contents
print_block()-> valid block data of size 32 at 00E96C70
fill char is 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
after free()
print_block() -> block is null.
完整代碼
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
size_t size;
uint8_t fill;
uint8_t* data;
} Block;
Block* free_block(Block*);
Block* get_block(size_t size, uint8_t fill_value);
void print_block(Block* block, const char* title);
int main(void)
{
const int test_size = 32;
Block* block = get_block(test_size, 0); // 3 bytes, zero filled
printf(
"Main()\t\t\t-> Pointer at %p points to data at "
"%p\n",
&block, block->data);
print_block(block, "\nBlock contents:");
block = free_block(block);
print_block(block, "\nafter free()");
return 0;
}
Block* free_block(Block* block)
{
if (block == NULL) return NULL;
if (block->data == NULL) return NULL;
free(block->data); // data is free
free(block);
return NULL;
}
Block* get_block(size_t size, uint8_t fill)
{
Block* block = malloc(sizeof(Block));
if (block == NULL) return NULL;
block->data = malloc(size * sizeof(uint8_t));
if (block->data == NULL) return NULL;
memset(block->data, fill, size);
block->fill = fill;
block->size = size;
return block;
}
void print_block(Block* block, char* title)
{
if (title != NULL) printf("%s\n", title);
if (block == NULL)
{
printf("print_block()\t-> block is null.\n");
return;
}
printf(
"print_block()->\tvalid block data of size %d at "
"%p\n\t\tfill char is X\n\n",
block->size, block->data, block->fill);
// Print byte by byte
const int nc = 16; // 16 bytes per line
size_t j = 1;
for (size_t i = 0; i < block->size; i = 1)
{
printf("X ", block->data[i]);
if (j >= nc)
printf("\n"), j = 1;
else
j = 1;
}
if ( j != 1 ) printf("\n");
return;
}
uj5u.com熱心網友回復:
沒有標準的方法來判斷一個指標是否有效,它是否指向一個分配的物件,也沒有它是否已經被釋放。
然而,可以在分配函式之上設計一個框架來跟蹤所有分配和釋放,并維護一個有效指標串列。在此串列中查找指標值將告訴您指標是否指向有效分配的塊,以及可能從堆中請求的大小。
這是一個簡單的實作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void track_add_pointer(void *p, size_t size);
int track_find_pointer(void *p, size_t *sizep);
void track_remove_pointer(void *p);
void *tmalloc(size_t size) {
void *p = (malloc)(size);
if (p) {
track_add_pointer(p, size);
}
return p;
}
void *tcalloc(size_t size, size_t nmemb) {
void *p = (calloc)(size, nmemb);
if (p) {
track_add_pointer(p, size * nmemb);
}
return p;
}
void *trealloc(void *p, size_t size) {
if (p) {
void *newp = NULL;
if (!track_find_pointer(p, NULL)) {
fprintf(stderr, "trealloc: invalid pointer %p\n", p);
} else {
if (size == 0) {
(free)(p);
} else {
newp = (realloc)(p, size);
}
if (newp != p) {
if (p) track_remove_pointer(p);
if (newp) track_add_pointer(newp);
}
}
return newp;
} else {
return tmalloc(size);
}
}
void tfree(void *p) {
if (p) {
if (!track_find_pointer(p, NULL)) {
fprintf(stderr, "tfree: invalid pointer %p\n", p);
} else {
(free)(p);
track_remove_pointer(p);
}
}
}
char *tstrdup(const char *s) {
char *p = NULL;
if (s) {
size_t len = strlen(s);
p = tmalloc(len 1);
if (p) {
memcpy(p, s, len 1);
}
} else {
fprintf(stderr, "tstrdup: null pointer\n");
}
return p;
}
char *tstrndup(const char *s, size_t n) {
char *p = NULL;
if (s) {
size_t len = strnlen(s, n);
p = tmalloc(len 1);
if (p) {
memcpy(p, s, len);
p[len] = '\0';
}
} else {
fprintf(stderr, "tstrndup: null pointer\n");
}
return p;
}
uj5u.com熱心網友回復:
首先,您需要知道將free(p)
記憶體塊標記為可用于任何新分配,僅此而已;并且p
它本身的指標仍然是一個有效指標,您可以從中讀取和寫入。
關于您的問題“如何檢測記憶體塊是否已被釋放? ”C 中的簡短回答是沒有辦法。要解決這個問題,你肯定需要一個指標跟蹤器,這并不難,這是一個例子:
void *ptr_list[64];
int ptr_position = 0;
bool ptr_exist(void *p) {
if(p == NULL)
return false;
for(int i = 0; i < ptr_position; i ) {
if(ptr_list[i] == p)
return true;
}
return false;
}
void ptr_add(void *p) {
if(p == NULL)
return;
if(!ptr_exist(p)) {
for(int i = 0; i < ptr_position; i ) {
if(ptr_list[i] == NULL) {
ptr_list[i] = p;
return;
}
}
ptr_list[ptr_position] = p;
ptr_position ;
}
}
void ptr_free(void **p) {
if(*p == NULL)
return;
for(int i = 0; i < ptr_position; i ) {
if(ptr_list[i] == *p) {
ptr_list[i] = NULL;
}
}
for(int i = ptr_position; i >= 0; i--) {
if(ptr_list[i] == NULL) {
ptr_position = i;
break;
}
}
free(*p);
*p = NULL;
}
要在分配記憶體塊后使用它,請將指標添加到跟蹤器 using ptr_add()
,并在您想要釋放它時使用ptr_free()
. 最后,您可以隨時從任何執行緒檢查此記憶體塊是否仍然有效,使用ptr_exist()
.
結果和完整代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// -- Pointers Tracker --
void *ptr_list[64];
int ptr_position = 0;
bool ptr_exist(void *p) {
if(p == NULL)
return false;
for(int i = 0; i < ptr_position; i ) {
if(ptr_list[i] == p)
return true;
}
return false;
}
void ptr_add(void *p) {
if(p == NULL)
return;
if(!ptr_exist(p)) {
for(int i = 0; i < ptr_position; i ) {
if(ptr_list[i] == NULL) {
ptr_list[i] = p;
return;
}
}
ptr_list[ptr_position] = p;
ptr_position ;
}
}
void ptr_free(void **p) {
if(*p == NULL)
return;
for(int i = 0; i < ptr_position; i ) {
if(ptr_list[i] == *p) {
ptr_list[i] = NULL;
}
}
for(int i = ptr_position; i >= 0; i--) {
if(ptr_list[i] == NULL) {
ptr_position = i;
break;
}
}
free(*p);
*p = NULL;
}
// ----------------------
void free_block(u_int8_t *block) {
// Info
printf("free_block()\t-> %p Point To %p \n", &block, block);
// Free Block
// free(block);
// block = NULL;
ptr_free((void *)&block);
}
void print_block(u_int8_t *block) {
// Detectc if this block is freed
// This is the objective of this code
if(!ptr_exist(block)) {
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("0xX ", *(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));
// Add it to the tracker
ptr_add((void *)block);
// 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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/470460.html
上一篇:列印矩陣行的函式