Smart pointers for the (GNU) C programming language

Overview

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.

Issues
  • sentinel uneeded in variadic macro pattern

    sentinel uneeded in variadic macro pattern

    The use of the sentinel in the variadic macro pattern is not necessary. The following is valid C and compiles using both gcc-4.4.7 and clang-3.4.2.

    edit: Clang also produces no compiler warnings at -Wextra. I understand the desire to maintain ISO compatibility, however, this was not apparent as other GCC/Clang extensions are used, such as the named variadic macro.

    edit2: missing context from blog post:

    Because the cleanup attribute is a compile time feature, I was going to play around with this on an embedded system like an AVR chip or similar target, where every single bit of RAM counts (most of my stock of AVR chips are 128-512 bytes of ram).

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define valloc( T, ...)                \
        ({                                  \
            struct _tmp {                   \
                __typeof__(T) value;        \
            } args = {                      \
                __VA_ARGS__                        \
            };                              \
            void * new = malloc(sizeof(T));  \
            if ( new != NULL)               \
                memcpy( new, &args.value, sizeof(T)); \
            new;                        \
        })
    
    struct vfunc_params {
        int a;
    };
    
    void vfunc_real( struct vfunc_params *args) {
        printf("vfunc_param->a = %#x\n", args->a);
    }
    
    #define vfunc(...) \
        vfunc_real( &(struct vfunc_params) { __VA_ARGS__ })
    
    int main( int argc, char * argv[])
    {
        int * x = 0;
    
        x = valloc( int );
        printf("valloc returned -> %#x\n", *x);
        free(x);
    
        x = valloc( int, 0xBAD0BEEF);
        printf("valloc returned -> %#x\n", *x);
        free(x);
    
        vfunc();
        vfunc(42);
    
        return 0;
    }
    
    opened by zschoenstadt 6
  • Fail to compile

    Fail to compile

    I can't compile the project. Here is the output:

    /tmp/libcsptr/check/test/utils.h: In function ‘make_test_case’: /tmp/libcsptr/check/test/utils.h:26:28: error: passing argument 2 of ‘_tcase_add_test’ from incompatible pointer type [-Werror=incompatible-pointer-types] 26 | tcase_add_test(tc, f); | ^ | | | TFun {aka void ()(int)} /usr/include/check.h:331:69: note: expected ‘const TTest *’ {aka ‘const struct TTest ’} but argument is of type ‘TFun’ {aka ‘void ()(int)’} 331 | CK_DLL_EXP void CK_EXPORT _tcase_add_test(TCase * tc, const TTest * ttest, | ~~~~~~~~~~~~~~^~~~~ cc1: all warnings being treated as errors

    However without libcheck installed, I can compile without problem

    opened by Skallwar 5
  • Problem with ... error: invalid conversion from ‘void*’ to ‘void**’

    Problem with ... error: invalid conversion from ‘void*’ to ‘void**’

    I was getting

    /usr/include/csptr/smart_ptr.h: In function ‘void sfree_stack(void*)’:
    /usr/include/csptr/smart_ptr.h:33:23: error: invalid conversion from ‘void*’ to ‘void**’ [-fpermissive]
         void **real_ptr = ptr;
                           ^
    make: *** [src/Test.o] Error 1
    
    

    which I fixed by changing line void **real_ptr = ptr; to void **real_ptr = (void**)ptr;

    opened by brewmanz 5
  • How can you implement the great smart attribute?!

    How can you implement the great smart attribute?!

    It's so wonderful that you implement the smart type attribute!
    Could you tell me how you did this? I can't find doc related to user defined type attribute for C/C++, but only user defined type.
    Thank you very much!

    opened by eaglexiang 2
  • Trying to understand the two available options more clearly

    Trying to understand the two available options more clearly

    In the build descriptionf file, you define two custom options - one for a variadic sentinel, the other to always use malloc. This might sound stupid, but what's the idea behind that? I'm basically trying to understand your code, and this is currently eluding me. Could you please help me understand?

    opened by kozross 2
  • Q. Why didn't you use C++ you moron?

    Q. Why didn't you use C++ you moron?

    Q. Why didn't you use C++ you moron?

    A. Because C makes smaller and faster executables. There is no ABI which is not made for C. Using C, I can focus on the job done. Using C++, one first has to satisfy the language[1], and just then one can try and get the job done.

    defer is coming into ISO C (gasp!) Good read for us C "morons", who use clang or gnuc __cleanup__

    [1] What do I mean by "satisfy the language"? motivation section of this paper explains it clearly

    opened by DBJDBJ 1
  • missing common.h

    missing common.h

    Hi, it seems, that the make && make install does not copy the common.h into the include directory, so that including smart_ptr.h in an application fails:

    `In file included from vdpau_private.h:40:0, from handles.c:23: /usr/local/include/csptr/smart_ptr.h:29:21: fatal error: common.h: No such file or directory

    include "common.h"

                     ^
    

    compilation terminated.`

    Copying common.h manually solved the problem here. The three other *.h are there ...

    Regards rellla

    opened by rellla 1
  • Missing message macro in AC_CHECK_LIB call

    Missing message macro in AC_CHECK_LIB call

    Running configure results in the following message:

    checking for srunner_run_all in -lcheck... no
    ../../../dependencies/csptr/configure: line 12116: Could: command not found
    checking whether ln -s works... yes
    

    I think you probably wanted AC_MSG_ERROR/AC_MSG_NOTICE

    Here is the line in question: https://github.com/Snaipe/c-smart-pointers/blob/master/configure.ac#L16

    opened by bturrubiates 1
  • Requiring smart pointers to be initialized

    Requiring smart pointers to be initialized

    In C++, unique_ptr and shared_ptr require a value, since they have ownership over it -- but in this case, since we don't wrap a pointer but return actual unintialized memory, I was wondering if the unique_ptr and shared_ptr macro should take a mandatory value and initialize the memory with it.

    Usage would be:

    smart int *some_int = unique_ptr(int, (1));
    smart double *some_array = unique_ptr(double[4], ({1, 2.5, 3.2, 0.999}), some_dtor);
    smart long *some_zero_padded_array = unique_ptr(long[25], ({1}), &some_meta, sizeof (some_meta));
    
    struct { 
        int a;
        long b;
        double c;
    } s;
    smart struct s *some_struct = unique_ptr(struct s, ({ .a = 1, .b = 2 }), dtor, &some_meta, sizeof (some_meta));
    

    Parenthesis over the value are unfortunate, but would be mandatory to allow struct and array literals to be passed, since curly braces are known to not group commas together in macro parameters.

    I am still not sure about that to be honest since one could desire to initialize the memory in a more specific way, but to be fair, that's what smalloc should be for.

    enhancement question 
    opened by Snaipe 1
  • Reassignement ?

    Reassignement ?

    I am a big fan of bringing unique_ptr to GNU C. But I think there is a difference beetween your repo and the cpp standard: reading this https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D What happens if I reassign a value ? Is this GNU-C undefined behaviour ?

    Reading the exemples, you never return unique_ptr from functions. Again, if it is not possible, it is a key difference with c++ unique_ptr.

    opened by cppmadguy 0
  • Unable to create dynamic arrays (i.e. size not known at compile time)

    Unable to create dynamic arrays (i.e. size not known at compile time)

    I can write code like smart char* pStrA = (char*)smart_arr(UNIQUE, char, 64); but not smart char* pStrA = (char*)smart_arr(UNIQUE, char, myArraySize); Can you give me any ideas what I need to do? Either with using csptr, or changing it. Thanks

    opened by brewmanz 3
  • Suggestion on smart arrays

    Suggestion on smart arrays

    Firstly, I must commend you on a very nice library here. Creating a library for smarter pointers in C and doing it in a way that is compatible with the syntax and style of the language is a real step forward for people like me who want to try high-level programming in C. Keep up the good work, and I'd be curious to hear if you have any plans for further features/updates. (I like that it's a small library right now though, and quite minimalistic as is C as a whole.)

    Regarding "smart arrays" specifically: I like that the library can infer the size of fixed-size arrays and use this to automate the destructor more. However, I personally imagine that implementing this in another way would be more general and extensible:

    1. For any fixed-size array type, set the default metadata to a size_t containing that size, and also set the default destructor to a function that does sfree on each element of the array (if the element type is a pointer) and nothing (if the element type is a non-pointer).
    2. Allow the metadata and destructor for the array to be override the defaults when they are specified as normal in the unique_ptr or shared_ptr macro call.

    Anyway, let me know what you think, and maybe we can establish what sort of interface for smart arrays is best. The design of the library in general is great, of course. :)

    opened by alexreg 4
Releases(v2.0.3)
  • v2.0.3(Jun 10, 2015)

  • v2.0.2(Apr 26, 2015)

  • v2.0.1(Apr 14, 2015)

  • v2.0.0(Mar 19, 2015)

    Warning: breaking changes to the interface

    • Removed the destructor helper macro
    • Changed the vararg usage to struct vararg. This change is NOT backward-compatible. Parenthesis around the value were removed with this change, and metadata is no longer passed as two separate parameters.
    • OS X and Windows support
    Source code(tar.gz)
    Source code(zip)
  • v1.0(Jan 26, 2015)

    • Smart pointers now take a mandatory value. Uninitialized smart pointers may still be retrieved with a direct call to smalloc.
    • Fixed some typos and updated documentation & samples to fit the latest interface.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Jan 20, 2015)

    • Removed --with-malloc-wrapper ./configure flag.
    • Removed malloc/free wrappers.
    • Added unit tests & coverage reports.
    • Fix for shared pointers accessing the wrong metadata.
    Source code(tar.gz)
    Source code(zip)
  • v0.3(Jan 20, 2015)

    • Added --with-malloc-wrapper and --with-fixed-allocator flags for ./configure.
    • Added a fixed allocator support -- if the user does not want to override at runtime the allocators used by smalloc/sfree and just want to use malloc and free, they may enable this option using the --with-fixed-allocator configuration flag.
    • Added malloc/free wrappers. Pointers produced by malloc can be used with the smart attribute, and smart pointers may be passed to free. This option is deactivated by default, and can be enabled using the --with-malloc-wrapper configuration flag.
    Source code(tar.gz)
    Source code(zip)
  • v0.2(Jan 20, 2015)

    • unique_ptr and shared_ptr now take a type parameter instead of a size.
    • Added support for static array types in the unique_ptr and shared_ptr macros.
    • Added smart array allocation through smalloc. smalloc has been changed to take a mandatory nmemb parameter, that may be 0 if the allocated type is a scalar, and an array for any other value.
    Source code(tar.gz)
    Source code(zip)
  • v0.1(Jan 20, 2015)

    • Added unique_ptr and shared_ptr macros, added smart variable attribute.
    • Added smalloc, sfree, sref, and get_smart_user_meta. Alternative allocators may be specified by setting the contents of smalloc_allocator.
    Source code(tar.gz)
    Source code(zip)
Owner
Franklin Mathieu
Building C tools for the 21st century
Franklin Mathieu
C++ Type Traits for Smart Pointers that are not included in the standard library, containing inheritance detection and member detection.

Smart Pointer Type Trait ?? A simple, header-only cpp library implementing smart pointer type traits. You can easily compile your code diffrently depe

Woon2 11 Dec 22, 2021
✔️The smallest header-only GUI library(4 KLOC) for all platforms

Welcome to GUI-lite The smallest header-only GUI library (4 KLOC) for all platforms. 中文 Lightweight ✂️ Small: 4,000+ lines of C++ code, zero dependenc

null 6.2k May 13, 2022
Calido - Open Smart Thermostat and Smart Home Controller. Built on a Thingy:91 (nRF9160).

Calido - Open Smart Thermostat and Smart Home Controller based on a Nordic Semiconductor Thingy:91 Project can be found here (Electromaker.io). A Make

ticccco 2 May 11, 2022
C++ DataFrame for statistical, Financial, and ML analysis -- in modern C++ using native types, continuous memory storage, and no pointers are involved

C++ DataFrame for statistical, Financial, and ML analysis -- in modern C++ using native types, continuous memory storage, and no pointers are involved

Hossein Moein 1.5k May 12, 2022
struct_san is a vulnerability prevention tool that dynamically detects function pointers in kernel structures

struct_san - struct sanitizer 简介 struct_san是一个动态检测内核结构体函数指针的漏洞防御工具。业界对于结构体函数指针的保护主要集中在 Control-Flow Integrity (CFI),也就是关注在控制流上,没有关注在数据流上,例如某些CFI验证函数指针

YunDing Security Lab 19 May 6, 2022
Solidity, the Smart Contract Programming Language

The Solidity Contract-Oriented Programming Language You can talk to us on Gitter and Matrix, tweet at us on Twitter or create a new topic in the Solid

null 16.6k May 13, 2022
PLP Project Programming Language | Programming for projects and computer science and research on computer and programming.

PLPv2b PLP Project Programming Language Programming Language for projects and computer science and research on computer and programming. What is PLP L

PLP Language 5 Apr 11, 2022
StarkScript - or the Stark programming language - is a compiled C-based programming language that aims to offer the same usability as that of JavaScript's and TypeScript's

StarkScript StarkScript - or the Stark programming language - is a compiled C-based programming language that aims to offer the same usability as that

EnderCommunity 5 May 10, 2022
frost is a programming language with a focus on low-friction systems programming.

❄️ frost frost programming language About frost is a programming language with a focus on low-friction systems programming.

null 4 Nov 12, 2021
Programming Language T#. Compiled language. In development.

Programming Language T# WARNING! THIS LANGUAGE IS A WORK IN PROGRESS! ANYTHING CAN CHANGE AT ANY MOMENT WITHOUT ANY NOTICE! $ make func main() {

Ibuki Yoshida 1 Feb 1, 2022
T# Programming Language. Interpreted language. In development. I will make this compilable later.

The T# Programming Language WARNING! THIS LANGUAGE IS A WORK IN PROGRESS! ANYTHING CAN CHANGE AT ANY MOMENT WITHOUT ANY NOTICE! Install Install $ make

T# 90 May 11, 2022
The Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.

Wren is a small, fast, class-based concurrent scripting language Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a fami

Wren 5.6k May 9, 2022
GNU Prolog is a native Prolog compiler

GNU Prolog is a native Prolog compiler with constraint solving over finite domains (FD)

Daniel Diaz 52 May 11, 2022
Minimal Linux Live (MLL) is a tiny educational Linux distribution, which is designed to be built from scratch by using a collection of automated shell scripts. Minimal Linux Live offers a core environment with just the Linux kernel, GNU C library, and Busybox userland utilities.

Minimal Linux Live (MLL) is a tiny educational Linux distribution, which is designed to be built from scratch by using a collection of automated shell scripts. Minimal Linux Live offers a core environment with just the Linux kernel, GNU C library, and Busybox userland utilities.

John Davidson 1.3k May 11, 2022
A few standalones demodulators replacing GNU Radio flowcharts

Standalone-Demodulators A few standalones demodulators replacing GNU Radio flowcharts. Still WIP! But usable. QPSK Demodulator Simple QPSK demodulator

Altillimity 39 Apr 21, 2022
Audacity is an easy-to-use, multi-track audio editor and recorder for Windows, Mac OS X, GNU/Linux and other operating systems

Audacity is an easy-to-use, multi-track audio editor and recorder for Windows, Mac OS X, GNU/Linux and other operating systems. Audacity is open source software licensed under GPL, version 2 or later.

Audacity 7.5k May 14, 2022
Sneedacity (formerly Audacity) is an easy-to-use, multi-track audio editor and recorder for Windows, Mac OS X, GNU/Linux and other operating systems.

Sneedacity (formerly Audacity) is an easy-to-use, multi-track audio editor and recorder for Windows, Mac OS X, GNU/Linux and other operating systems. Sneedacity is open source software licensed under GPL, version 2 or later.

Sneed's Feed & Seed 864 May 13, 2022
Tenacity is an easy-to-use, cross-platform multi-track audio editor/recorder for Windows, MacOS, GNU/Linux

Tenacity is an easy-to-use, cross-platform multi-track audio editor/recorder for Windows, MacOS, GNU/Linux and other operating systems and is developed by a group of volunteers as open source software.

null 7.1k May 11, 2022
Isocline is a pure C library that can be used as an alternative to the GNU readline library

Isocline: a portable readline alternative. Isocline is a pure C library that can be used as an alternative to the GNU readline library (latest release

Daan 111 May 8, 2022
FNC is an Extremely lightweight C++ remake of GNU Cat

FNC is an barebones recreation of GNU CAT in C++ that removes unecessary options, which could be useful if you need to shave down a system to the kilobytes.

null 5 Dec 3, 2021
GNU project's implementation of the standard C library(with Xuantie RISC-V CPU support).

GNU project's implementation of the standard C library(with Xuantie RISC-V CPU support).

T-Head Semiconductor Co., Ltd. 5 Mar 17, 2022
A FLOSS implementation of the ground breaking MacBook camera system for GNU/Linux

GNU/Notch Tired of your friends making fun of your dinosaur laptop? Can't afford anything but Free Software? Fret not for this simple X11 based progra

null 2 Oct 30, 2021
emily - GNU/Linux applications and scripts launcher.

emily emily - GNU/Linux applications and scripts launcher. For What? Firstly emily has been maden as a replacement for i3-dmenu, because i don't like

null 1 May 13, 2022
An ATSC 3.0 Transmitter for GNU Radio

# Copyright 2021 Ron Economos # # This file is part of gr-atsc3 # # gr-atsc3 is free software; you can redistribute it and/or modify # it under the te

Ron Economos 11 Mar 16, 2022
vplot is a wrapper for GNU Plot (gnuplot_i)

vplot vplot is a wrapper for GNU Plot (gnuplot_i). The source of gnuplot_i I have downloaded from this link. Files listed on gnuplot_i are taken from

Erdet Nasufi 9 May 9, 2022
Simple Fetch Software for GNU/Linux

ponyfetch Simple Fetch Software for GNU/Linux Current Version: 1.2 Whats new in 1.2? You can now change the ASCII art and the labels used in ponyfetch

FlutterHeart the Alicorn 3 Nov 22, 2021
GNU project for mm32 chip

编译环境安装(以下是ubuntu上的示例) git 下载项目工程 git clone https://github.com/YanMinge/mm32_project_demo 下载最新的 gcc开发环境 sudo apt-get install sudo apt-get install gcc-a

Mark Yan 2 Mar 31, 2022
Simple-MySQL-API is a free and easy API to manipulate MySQL with C99 and GCC compiler under GNU/Linux OS.

Simple-MySQL-API is a free and easy API to manipulate MySQL with C99 and GCC compiler under GNU/Linux OS.

Neptune 7 Apr 24, 2022