- Notifications
You must be signed in to change notification settings - Fork147
Smart pointers for the (GNU) C programming language
License
Snaipe/libcsptr
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This project is an attempt to bring smart pointer constructsto the (GNU) C programming language.
unique_ptr
,shared_ptr
macros, andsmart
type attribute- Destructor support for cleanup
- Custom variable metadata on allocation
- Cross-platform: tested under linux 3.18.6-1, Mac OS X Yosemite 10.10, and Windows 7 (with MinGW and the Cygwin port of GCC)
Mac OS X:
brew install snaipe/soft/libcsptr
AUR:
yaourt -S libcsptr
Ubuntu:
$ sudo add-apt-repository ppa:snaipewastaken/ppa$ sudo apt-get update$ sudo apt-get install libcsptr-dev
To compile the library, GCC 4.6+ is needed.
- Clone this repository
- run
mkdir build && cd $_ && cmake -DCMAKE_INSTALL_PREFIX=$HOME .. && make && make install
from the project root for a local install, or runmkdir build && cd $_ && cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make && sudo make install
for a global install.
- Simple unique_ptr:simple1.c:Shell session:
#include<stdio.h>#include<csptr/smart_ptr.h>intmain(void) {// some_int is an unique_ptr to an int with a value of 1.smartint*some_int=unique_ptr(int,1);printf("%p = %d\n",some_int,*some_int);// some_int is destroyed herereturn0;}
$ gcc -std=c99 -o simple1 simple1.c -lcsptr$ valgrind ./simple1==3407== Memcheck, a memory error detector==3407== Copyright (C) 2002-2013, and GNU GPL\'d, by Julian Seward et al.==3407== Using Valgrind-3.10.0 and LibVEX; rerun with -hfor copyright info==3407== Command: ./test1==3407==0x53db068 = 1==3407====3407== HEAP SUMMARY:==3407==in use at exit: 0 bytesin 0 blocks==3407== total heap usage: 1 allocs, 1 frees, 48 bytes allocated==3407====3407== All heap blocks were freed -- no leaks are possible==3407====3407== For counts of detected and suppressed errors, rerun with: -v==3407== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
- Simple unique_ptr with destructor:
#include<unistd.h>#include<fcntl.h>#include<csptr/smart_ptr.h>structlog_file {intfd;// ...};voidcleanup_log_file(void*ptr,void*meta) { (void)meta;close(((structlog_file*)ptr)->fd);}intmain(void) {smartstructlog_file*log=unique_ptr(structlog_file, { .fd=open("/dev/null",O_WRONLY |O_APPEND),// ... },cleanup_log_file);write(log->fd,"Hello",5);// cleanup_log_file is called, then log is freedreturn0;}
- Allocating a smart array and printing its contents before destruction:
#include<stdio.h>#include<csptr/smart_ptr.h>#include<csptr/array.h>voidprint_int(void*ptr,void*meta) { (void)meta;// ptr points to the current element// meta points to the array metadata (global to the array), if any.printf("%d\n",*(int*)ptr);}intmain(void) {// Destructors for array types are run on every element of the// array before destruction.smartint*ints=unique_ptr(int[5], {5,4,3,2,1},print_int);// ints == {5, 4, 3, 2, 1}// Smart arrays are length-awarefor (size_ti=0;i<array_length(ints);++i) {ints[i]=i+1; }// ints == {1, 2, 3, 4, 5}return0;}
Using a different memory allocator (although most will replace malloc/free):
#include<csptr/smart_ptr.h>void*some_allocator(size_t);voidsome_deallocator(void*);intmain(void) {smalloc_allocator= (s_allocator) {some_allocator,some_deallocator};// ...return0;}
Automatic cleanup on error cases:
#include<unistd.h>#include<fcntl.h>#include<csptr/smart_ptr.h>structlog_file {intfd;// ...};staticvoidclose_log(void*ptr,void*meta) { (void)meta;structlog_file*log=ptr;if (log->fd!=-1)close(log->fd);}structlog_file*open_log(constchar*path) {smartstructlog_file*log=shared_ptr(structlog_file, {0},close_log);if (!log)// failure to allocatereturnNULL;// nothing happens, destructor is not calledlog->fd=open(path,O_WRONLY |O_APPEND |O_CREAT,0644);if (log->fd==-1)// failure to openreturnNULL;// log gets destroyed, file descriptor is not closed since fd == -1.returnsref(log);// a new reference on log is returned, it does not get destoyed}intmain(void) {smartstructlog_file*log=open_log("/dev/null");// ...return0;// file descriptor is closed, log is freed}
Using named parameters:
#include<csptr/smart_ptr.h>voidnothing(void*ptr,void*meta) {}intmain(void) {struct {inta; }m= {1 };smartint*i=unique_ptr(int, .dtor=nothing, .value=42, .meta= {&m,sizeof (m) } );return0;}
Q. Why didn't you use C++ you moron ?
A. Because when I first started this, I was working on a C project.Also, because it's fun.
Q. Can I use this on a serious project ?
A. Yes, but as this project has not been widely used, there might besome bugs. Beware!
Q. How did you make this ?
A. Here's alink to my blog post on the matter.
About
Smart pointers for the (GNU) C programming language