I am a programmer with a primarily Rust-based background who has nonetheless taken an interest in C lately due to its simplicity and minimalism. However, one of the things I miss most from Rust is safe memory management. So I created a "smart pointer" of sorts to replicate that experience:
#include <stdio.h>
/*
This is a "smart" pointer that
uses Option types for safe memory management.
*/
typedef enum option {
Some,
None
} Option;
typedef struct OptionPointer {
void *content;
Option state;
int is_malloc;
} OptionPointer;
union internal_PointerType {
void *content;
int err;
};
typedef struct PointerType {
int choice;
union internal_PointerType internal;
} PointerType;
OptionPointer create_ptr(void *content, int is_malloc) {
OptionPointer p;
p.content = content;
p.state = Some;
p.is_malloc = is_malloc;
return p;
}
void set_ptr_invalid(OptionPointer *ptr) {
ptr->state = None;
// Only need to free memory
// if it was dynamically allocated,
// otherwise we only need to worry
// about dangling pointers
if (ptr->is_malloc) {
free(ptr->content);
}
}
PointerType get_ptr(OptionPointer *ptr) {
PointerType res;
res.choice = 0;
if (ptr->state == None) {
res.choice = 0;
res.internal.err = 1;
} else {
res.choice = 1;
res.internal.content = ptr->content;
}
return res;
}
// Example
int main() {
char *a = "This is some testing text";
OptionPointer ptr = create_ptr(a, 0);
// Imaginary scenario where the pointer becomes invalid
set_ptr_invalid(&ptr);
PointerType res = get_ptr(&ptr);
if (res.choice) {
char *content = (char*)res.internal.content;
printf("%s\n", content);
} else {
printf("Invalid pointer at %s:%d\n", __FILE__, __LINE__);
}
}
I can already see some notable problems:
- I literally just started programming in C a few days ago so I probably am not using recommended best practices
- "Smart" only goes so far - you'd have to call
set_ptr_invalid()
every single time a pointer could become invalid as a result of an operation - This (possibly?) might not work well with
malloc()
and doesn't cover the case thatmalloc()
wasn't successful
All feedback on this would be much appreciated!
void *
in C. You don't need to cast avoid *
to achar *
. 2) Usebool
,true
, andfalse
fromstdbool.h
to denote a binary state. \$\endgroup\$set_ptr_invalid()
does not check for the current state and thus is prone to multiple-free bugs if called repeatedly. \$\endgroup\$