• Stars
    star
    1,456
  • Rank 31,037 (Top 0.7 %)
  • Language CMake
  • License
    MIT License
  • Created over 9 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Smart pointers for the (GNU) C programming language

C Smart Pointers

Build Status Coverage Status License Version

What this is

This project is an attempt to bring smart pointer constructs to the (GNU) C programming language.

Features

  • unique_ptr, shared_ptr macros, and smart 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)

Installing

With a package manager

  • 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

Building from source

Prerequisites

To compile the library, GCC 4.6+ is needed.

Installation

  1. Clone this repository
  2. run mkdir build && cd $_ && cmake -DCMAKE_INSTALL_PREFIX=$HOME .. && make && make install
    from the project root for a local install, or run
    mkdir build && cd $_ && cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make && sudo make install for a global install.

Examples

  • Simple unique_ptr: simple1.c:
    #include <stdio.h>
    #include <csptr/smart_ptr.h>
    
    int main(void) {
        // some_int is an unique_ptr to an int with a value of 1.
        smart int *some_int = unique_ptr(int, 1);
    
        printf("%p = %d\n", some_int, *some_int);
    
        // some_int is destroyed here
        return 0;
    }
    Shell session:
    $ 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 -h for copyright info
    ==3407== Command: ./test1
    ==3407==
    0x53db068 = 1
    ==3407==
    ==3407== HEAP SUMMARY:
    ==3407==     in use at exit: 0 bytes in 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>
    
    struct log_file {
        int fd;
        // ...
    };
    
    void cleanup_log_file(void *ptr, void *meta) {
        (void) meta;
        close(((struct log_file *) ptr)->fd);
    }
    
    int main(void) {
        smart struct log_file *log = unique_ptr(struct log_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 freed
        return 0;
    }
  • Allocating a smart array and printing its contents before destruction:
    #include <stdio.h>
    #include <csptr/smart_ptr.h>
    #include <csptr/array.h>
    
    void print_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);
    }
    
    int main(void) {
        // Destructors for array types are run on every element of the
        // array before destruction.
        smart int *ints = unique_ptr(int[5], {5, 4, 3, 2, 1}, print_int);
        // ints == {5, 4, 3, 2, 1}
    
        // Smart arrays are length-aware
        for (size_t i = 0; i < array_length(ints); ++i) {
            ints[i] = i + 1;
        }
        // ints == {1, 2, 3, 4, 5}
    
        return 0;
    }

More examples

  • Using a different memory allocator (although most will replace malloc/free):

    #include <csptr/smart_ptr.h>
    
    void *some_allocator(size_t);
    void some_deallocator(void *);
    
    int main(void) {
        smalloc_allocator = (s_allocator) {some_allocator, some_deallocator};
        // ...
        return 0;
    }
  • Automatic cleanup on error cases:

    #include <unistd.h>
    #include <fcntl.h>
    #include <csptr/smart_ptr.h>
    
    struct log_file {
        int fd;
        // ...
    };
    
    static void close_log(void *ptr, void *meta) {
        (void) meta;
        struct log_file *log = ptr;
        if (log->fd != -1)
            close(log->fd);
    }
    
    struct log_file *open_log(const char *path) {
        smart struct log_file *log = shared_ptr(struct log_file, {0}, close_log);
        if (!log) // failure to allocate
            return NULL; // nothing happens, destructor is not called
    
        log->fd = open(path, O_WRONLY | O_APPEND | O_CREAT, 0644);
        if (log->fd == -1) // failure to open
            return NULL; // log gets destroyed, file descriptor is not closed since fd == -1.
    
        return sref(log); // a new reference on log is returned, it does not get destoyed
    }
    
    int main(void) {
        smart struct log_file *log = open_log("/dev/null");
        // ...
        return 0; // file descriptor is closed, log is freed
    }
  • Using named parameters:

    #include <csptr/smart_ptr.h>
    
    void nothing(void *ptr, void *meta) {}
    
    int main(void) {
        struct { int a; } m = { 1 };
    
        smart int *i = unique_ptr(int,
                .dtor = nothing,
                .value = 42,
                .meta = { &m, sizeof (m) }
            );
    
        return 0;
    }

FAQ

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 be some bugs. Beware!

Q. How did you make this ?
A. Here's a link to my blog post on the matter.

More Repositories

1

Criterion

A cross-platform C and C++ unit testing framework for the 21st century
C
1,884
star
2

wssdl

Wireshark-Specific Dissector Language
Lua
193
star
3

Mimick

A KISS, cross-platform C mocking library
C
148
star
4

fmem

A cross-platform library for opening memory-backed libc streams.
C
57
star
5

dot-git

Managing your dotfiles the Git Wayβ„’
Shell
44
star
6

BoxFort

Convenient & cross-platform sandboxing C library
C
40
star
7

python-rst2ansi

A python utility for rendering RST in the terminal
Python
32
star
8

confloose

The best startup scripts to prank IT people with
22
star
9

table2ascii

A simple proof of concept for rendering tables in ascii
Python
21
star
10

malloc

Simple malloc implementation for POSIX systems w/ sbrk(2)
C
18
star
11

toy-containers

Fast, lightweight toy container system
Go
11
star
12

Tizzy

A C library dedicated to error handling and panicking.
C
9
star
13

dyncall

Git mirror of http://hg.dyncall.org/pub/dyncall/dyncall
C
8
star
14

Insight

A reflection library for C and C++
C++
5
star
15

lastpass-ssh-agent

A SSH agent that authenticates you from keys in your lastpass vault
C
5
star
16

ttysend

A simplistic C utility to send data to other tty/pts.
C
4
star
17

colorutils

A small linux (command-line) utility to make the framebuffer a splashscreen
C
3
star
18

gitlab-runner-kubevirt

A gitlab-runner custom executor driver for running jobs with Kubevirt
Go
3
star
19

Tequila

A Minecraft server manager
Python
3
star
20

x-nix

A linux compatibility layer for multiple platforms
C
3
star
21

go-htutil

Go HTTP utilities, with no dependencies
Go
2
star
22

arm-stm32l1

A sample project for the stm32l1 using libopencm3
C
2
star
23

.files

My dotfiles. Check https://github.com/Snaipe/dot-git for the workflow.
Python
2
star
24

go-pass

Prompting passwords securely in Go
Go
2
star
25

sweet

A sway-to-i3 IPC compatibility layer
Go
2
star
26

Thieves

A thief plugin for Bukkit
Java
2
star
27

boa

Better configuration management in Go
Go
2
star
28

articles

Articles on http://snaipe.me/
2
star
29

metaheuristic

Python
2
star
30

packages

Packaging sources for my software
Shell
1
star
31

go-pager

A Go writer that abstracts `$PAGER` in a POSIX-compliant way.
Go
1
star
32

BlackDog

A Bukkitdev-to-maven-repository mapper
Python
1
star
33

go-hterrors

Convenience library for handling non-2xx HTTP errors
Go
1
star
34

Vapor

A java library for p2p sharing
Java
1
star
35

docker-alpine-qemu

Foreign-arch docker images running on x86_64 hosts.
Shell
1
star
36

meson-check

A meson module to conveniently check for features
Python
1
star
37

Damon

Functional constructs for the D programming language
D
1
star
38

libdwarfplusplus

A C++ wrapper over libdwarf
C++
1
star