Skip to content

Instantly share code, notes, and snippets.

@nicholaschiasson
Last active July 9, 2019 09:36

Revisions

  1. nicholaschiasson revised this gist Aug 13, 2017. 2 changed files with 4 additions and 2 deletions.
    3 changes: 2 additions & 1 deletion MapMemMon.h
    Original file line number Diff line number Diff line change
    @@ -120,7 +120,8 @@ inline size_t MapMemMon::Delete(T * data)
    {
    allocatedMemory->erase((void *)data);
    bytesDeleted = dataSize;
    if (allocatedMemory->empty()) {
    if (allocatedMemory->empty())
    {
    Cleanup();
    }
    }
    3 changes: 2 additions & 1 deletion SetMemMon.h
    Original file line number Diff line number Diff line change
    @@ -107,7 +107,8 @@ inline void SetMemMon::Delete(T * data, bool isArray)
    if (allocatedMemory != 0)
    {
    allocatedMemory->erase((void *)data);
    if (allocatedMemory->empty()) {
    if (allocatedMemory->empty())
    {
    Cleanup();
    }
    }
  2. nicholaschiasson revised this gist May 4, 2017. 1 changed file with 21 additions and 0 deletions.
    21 changes: 21 additions & 0 deletions LICENSE
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    MIT License

    Copyright (c) 2017 Nicholas Omer Chiasson

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
  3. Nicholas Omer Chiasson revised this gist Feb 9, 2017. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,21 @@
    OS := $(shell uname)
    ifneq "$(OS)" "Darwin"
    STATIC_FLAGS += -static
    endif

    speedtest_static: libmemmon.a
    g++ -std=c++11 -static speedtest.cpp -L${PWD} -lmemmon -o speedtest
    g++ -std=c++11 $(STATIC_FLAGS) speedtest.cpp -L${PWD} -lmemmon -o speedtest

    speedtest_dynamic: libmemmon.so
    g++ -std=c++11 speedtest.cpp -L${PWD} -lmemmon -o speedtest

    libmemmon.a:
    g++ -c -std=c++11 SetMemMon.cpp MapMemMon.cpp MemMon.cpp
    ar rcs libmemmon.a SetMemMon.o MapMemMon.o MemMon.o
    rm *.o

    libmemmon.so:
    g++ -fPIC -shared -std=c++11 SetMemMon.cpp MapMemMon.cpp MemMon.cpp -o libmemmon.so

    clean:
    rm -f speedtest *.so *.o *.a
    rm -f speedtest *.so *.o *.a
  4. Nick Chiasson revised this gist Jun 9, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -12,4 +12,4 @@ libmemmon.so:
    g++ -fPIC -shared -std=c++11 SetMemMon.cpp MapMemMon.cpp MemMon.cpp -o libmemmon.so

    clean:
    rm -f speedtest *.so *.o
    rm -f speedtest *.so *.o *.a
  5. Nick Chiasson revised this gist Jun 9, 2016. 1 changed file with 9 additions and 2 deletions.
    11 changes: 9 additions & 2 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,12 @@
    all: libmemmon.so
    g++ -std=c++11 -L${PWD} -lmemmon speedtest.cpp -o speedtest
    speedtest_static: libmemmon.a
    g++ -std=c++11 -static speedtest.cpp -L${PWD} -lmemmon -o speedtest

    speedtest_dynamic: libmemmon.so
    g++ -std=c++11 speedtest.cpp -L${PWD} -lmemmon -o speedtest

    libmemmon.a:
    g++ -c -std=c++11 SetMemMon.cpp MapMemMon.cpp MemMon.cpp
    ar rcs libmemmon.a SetMemMon.o MapMemMon.o MemMon.o

    libmemmon.so:
    g++ -fPIC -shared -std=c++11 SetMemMon.cpp MapMemMon.cpp MemMon.cpp -o libmemmon.so
  6. Nick Chiasson revised this gist May 31, 2016. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,8 @@
    all:
    g++ -o speedtest speedtest.cpp MemMon.cpp SetMemMon.cpp MapMemMon.cpp -std=c++11
    all: libmemmon.so
    g++ -std=c++11 -L${PWD} -lmemmon speedtest.cpp -o speedtest

    libmemmon.so:
    g++ -fPIC -shared -std=c++11 SetMemMon.cpp MapMemMon.cpp MemMon.cpp -o libmemmon.so

    clean:
    rm -f speedtest *.o
    rm -f speedtest *.so *.o
  7. Nick Chiasson revised this gist May 30, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions MemMon.h
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    #ifndef MEMMON_H
    #define MEMMON_H

    #include "SetMemMon.h"
    #include "MapMemMon.h"
  8. Nick Chiasson revised this gist May 6, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion speedtest.cpp
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@ int main(int argc, char *argv[])
    }
    t_finish = clock() - t_start;

    printf("%d clicks (%f seconds)\n", t_finish, ((float)t_finish) / CLOCKS_PER_SEC);
    printf("%ld clicks (%f seconds)\n", t_finish, ((float)t_finish) / CLOCKS_PER_SEC);
    printf("\n");
    }

  9. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion MemMon.md
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@ I also came up with two seperate static classes which are only really different
    - Find the macro definition for MEMMON_TYPE and set it to one of MAPMEMMON_TYPE, SETMEMMON_TYPE, or NULL_MEMMON_TYPE.
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    #### Keywork Macros
    #### Keyword Macros
    ###### void * mm_new(constructor)
    MemMon new expects to be passed a constructor of the type to allocate.

  10. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 0 additions and 62 deletions.
    62 changes: 0 additions & 62 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,62 +0,0 @@
    # MemMon Memory Monitors
    ###### NOT A GARBAGE COLLECTOR
    I decided to try my hand at making my code a bit safer as far as managing weak references goes, so I tried to make something to track references to memory locations. I soon thought that it was a stupid idea and simplified it so that it was simply the memory locations' validity which were being monitored. That way, all I needed to do was essentially a custom null check to see if my weak references were still valid. I tried to do this in the simplest and most aesthetically pleasing way as possible. Naturally, that means (to me) attempting to overload the new and delete keywords for every possible type. Well, since you can't do that, I decided to use macros :)

    I also came up with two seperate static classes which are only really different in that they use two different data structures.

    ## Usage
    #### Setup
    - Import the .cpp files into your project source and the .h files into your project headers.
    - Include only the MemMon.h file wherever you plan on using it.
    - Inside of MemMon.h is where you set your desired implementation (map, set, or none).
    - Find the macro definition for MEMMON_TYPE and set it to one of MAPMEMMON_TYPE, SETMEMMON_TYPE, or NULL_MEMMON_TYPE.
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    #### Keywork Macros
    ###### void * mm_new(constructor)
    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: `Foo *foo = mm_new(Foo(args));`

    ###### void * mm_new_a(type, count)
    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: `Foo *foo_arr = mm_new_a(Foo, 25);`

    ###### void mm_delete(data_ptr)
    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: `mm_delete(foo);`

    ###### void mm_delete_a(array_data_ptr)
    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: `mm_delete_a(foo_arr);`

    ###### bool mm_null(data)
    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: `bool dataIsNull = mm_null(foo);`

    ###### size_t mm_sizeof(data)
    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: `size_t foo_size = mm_sizeof(foo);`

    ###### size_t mm_count(data)
    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: `size_t foo_arr_count = mm_count(foo_arr);`

    ## SetMemMon
    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. Although the next iteration is more useful, I kept this one around just because of the slight speed compromise.

    ## MapMemMon
    Using a map, I stored a pointer to the address as the key and the number of bytes to be stored as the value. This way, I could ALSO perform a sizeof on any dynamically allocated arrays, and expanding on that, an element count as well! I am happy with the results and think that I will likely be using MapMemMon all the time in the future.

    ## Testing Results
    So for performance testing, among other stress tests, I basically just did a bunch of new array and delete array calls in a loop and compared the clock times with regular new[] and delete[] calls. I would say I am happy enough with the results, given the overhead. Should there be any curiosity, the following is the average of my results for a run of speedtest.cpp:

    - Regular new[] and delete[]: 160 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - SetMemMon new[] and delete[]: 370 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - MapMemMon new[] and delete[]: 580 clicks for 1000 allocated and deleted Foo arrays of size 1000
  11. Nick Chiasson renamed this gist May 3, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  12. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 62 additions and 1 deletion.
    63 changes: 62 additions & 1 deletion MemMon
    Original file line number Diff line number Diff line change
    @@ -1 +1,62 @@
    __name__
    # MemMon Memory Monitors
    ###### NOT A GARBAGE COLLECTOR
    I decided to try my hand at making my code a bit safer as far as managing weak references goes, so I tried to make something to track references to memory locations. I soon thought that it was a stupid idea and simplified it so that it was simply the memory locations' validity which were being monitored. That way, all I needed to do was essentially a custom null check to see if my weak references were still valid. I tried to do this in the simplest and most aesthetically pleasing way as possible. Naturally, that means (to me) attempting to overload the new and delete keywords for every possible type. Well, since you can't do that, I decided to use macros :)

    I also came up with two seperate static classes which are only really different in that they use two different data structures.

    ## Usage
    #### Setup
    - Import the .cpp files into your project source and the .h files into your project headers.
    - Include only the MemMon.h file wherever you plan on using it.
    - Inside of MemMon.h is where you set your desired implementation (map, set, or none).
    - Find the macro definition for MEMMON_TYPE and set it to one of MAPMEMMON_TYPE, SETMEMMON_TYPE, or NULL_MEMMON_TYPE.
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    #### Keywork Macros
    ###### void * mm_new(constructor)
    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: `Foo *foo = mm_new(Foo(args));`

    ###### void * mm_new_a(type, count)
    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: `Foo *foo_arr = mm_new_a(Foo, 25);`

    ###### void mm_delete(data_ptr)
    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: `mm_delete(foo);`

    ###### void mm_delete_a(array_data_ptr)
    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: `mm_delete_a(foo_arr);`

    ###### bool mm_null(data)
    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: `bool dataIsNull = mm_null(foo);`

    ###### size_t mm_sizeof(data)
    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: `size_t foo_size = mm_sizeof(foo);`

    ###### size_t mm_count(data)
    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: `size_t foo_arr_count = mm_count(foo_arr);`

    ## SetMemMon
    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. Although the next iteration is more useful, I kept this one around just because of the slight speed compromise.

    ## MapMemMon
    Using a map, I stored a pointer to the address as the key and the number of bytes to be stored as the value. This way, I could ALSO perform a sizeof on any dynamically allocated arrays, and expanding on that, an element count as well! I am happy with the results and think that I will likely be using MapMemMon all the time in the future.

    ## Testing Results
    So for performance testing, among other stress tests, I basically just did a bunch of new array and delete array calls in a loop and compared the clock times with regular new[] and delete[] calls. I would say I am happy enough with the results, given the overhead. Should there be any curiosity, the following is the average of my results for a run of speedtest.cpp:

    - Regular new[] and delete[]: 160 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - SetMemMon new[] and delete[]: 370 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - MapMemMon new[] and delete[]: 580 clicks for 1000 allocated and deleted Foo arrays of size 1000
  13. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions MemMon
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    __name__
  14. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 14 additions and 14 deletions.
    28 changes: 14 additions & 14 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -13,40 +13,40 @@ I also came up with two seperate static classes which are only really different
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    #### Keywork Macros
    ###### mm_new(constructor)
    ###### void * mm_new(constructor)
    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: Foo *foo = mm_new(Foo(args));
    Example usage: `Foo *foo = mm_new(Foo(args));`

    ###### mm_new_a(type, count)
    ###### void * mm_new_a(type, count)
    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: Foo *foo_arr = mm_new_a(Foo, 25);
    Example usage: `Foo *foo_arr = mm_new_a(Foo, 25);`

    ###### mm_delete(data_ptr)
    ###### void mm_delete(data_ptr)
    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: mm_delete(foo);
    Example usage: `mm_delete(foo);`

    ###### mm_delete_a(array_data_ptr)
    ###### void mm_delete_a(array_data_ptr)
    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: mm_delete_a(foo_arr);
    Example usage: `mm_delete_a(foo_arr);`

    ###### mm_null(data)
    ###### bool mm_null(data)
    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: bool dataIsNull = mm_null(foo);
    Example usage: `bool dataIsNull = mm_null(foo);`

    ###### mm_sizeof(data)
    ###### size_t mm_sizeof(data)
    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_size = mm_sizeof(foo);
    Example usage: `size_t foo_size = mm_sizeof(foo);`

    ###### mm_count(data)
    ###### size_t mm_count(data)
    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_arr_count = mm_count(foo_arr);
    Example usage: `size_t foo_arr_count = mm_count(foo_arr);`

    ## SetMemMon
    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. Although the next iteration is more useful, I kept this one around just because of the slight speed compromise.
  15. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -13,37 +13,37 @@ I also came up with two seperate static classes which are only really different
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    #### Keywork Macros
    ##### mm_new(constructor)
    ###### mm_new(constructor)
    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: Foo *foo = mm_new(Foo(args));

    ##### mm_new_a(type, count)
    ###### mm_new_a(type, count)
    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: Foo *foo_arr = mm_new_a(Foo, 25);

    ##### mm_delete(data_ptr)
    ###### mm_delete(data_ptr)
    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: mm_delete(foo);

    ##### mm_delete_a(array_data_ptr)
    ###### mm_delete_a(array_data_ptr)
    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: mm_delete_a(foo_arr);

    ##### mm_null(data)
    ###### mm_null(data)
    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: bool dataIsNull = mm_null(foo);

    ##### mm_sizeof(data)
    ###### mm_sizeof(data)
    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_size = mm_sizeof(foo);

    ##### mm_count(data)
    ###### mm_count(data)
    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_arr_count = mm_count(foo_arr);
  16. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 2 additions and 13 deletions.
    15 changes: 2 additions & 13 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,71 +1,60 @@
    # MemMon Memory Monitors

    ###### NOT A GARBAGE COLLECTOR

    I decided to try my hand at making my code a bit safer as far as managing weak references goes, so I tried to make something to track references to memory locations. I soon thought that it was a stupid idea and simplified it so that it was simply the memory locations' validity which were being monitored. That way, all I needed to do was essentially a custom null check to see if my weak references were still valid. I tried to do this in the simplest and most aesthetically pleasing way as possible. Naturally, that means (to me) attempting to overload the new and delete keywords for every possible type. Well, since you can't do that, I decided to use macros :)

    I also came up with two seperate static classes which are only really different in that they use two different data structures.

    ## Usage

    #### Setup
    - Import the .cpp files into your project source and the .h files into your project headers.
    - Include only the MemMon.h file wherever you plan on using it.
    - Inside of MemMon.h is where you set your desired implementation (map, set, or none).
    - Find the macro definition for MEMMON_TYPE and set it to one of MAPMEMMON_TYPE, SETMEMMON_TYPE, or NULL_MEMMON_TYPE.
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    #### Keywork Macros
    ##### mm_new(constructor)

    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: Foo *foo = mm_new(Foo(args));

    ##### mm_new_a(type, count)

    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: Foo *foo_arr = mm_new_a(Foo, 25);

    ##### mm_delete(data_ptr)

    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: mm_delete(foo);

    ##### mm_delete_a(array_data_ptr)

    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: mm_delete_a(foo_arr);

    ##### mm_null(data)

    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: bool dataIsNull = mm_null(foo);

    ##### mm_sizeof(data)

    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_size = mm_sizeof(foo);

    ##### mm_count(data)

    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_arr_count = mm_count(foo_arr);

    ## SetMemMon

    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. Although the next iteration is more useful, I kept this one around just because of the slight speed compromise.

    ## MapMemMon

    Using a map, I stored a pointer to the address as the key and the number of bytes to be stored as the value. This way, I could ALSO perform a sizeof on any dynamically allocated arrays, and expanding on that, an element count as well! I am happy with the results and think that I will likely be using MapMemMon all the time in the future.

    ## Testing Results

    So for performance testing, among other stress tests, I basically just did a bunch of new array and delete array calls in a loop and compared the clock times with regular new[] and delete[] calls. I would say I am happy enough with the results, given the overhead. Should there be any curiosity, the following is the average of my results for a run of speedtest.cpp:

    - Regular new[] and delete[]: 160 clicks for 1000 allocated and deleted Foo arrays of size 1000
  17. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -14,43 +14,43 @@ I also came up with two seperate static classes which are only really different
    - Find the macro definition for MEMMON_TYPE and set it to one of MAPMEMMON_TYPE, SETMEMMON_TYPE, or NULL_MEMMON_TYPE.
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    ### mm_new(constructor)
    ##### mm_new(constructor)

    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: Foo *foo = mm_new(Foo(args));

    ### mm_new_a(type, count)
    ##### mm_new_a(type, count)

    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: Foo *foo_arr = mm_new_a(Foo, 25);

    ### mm_delete(data_ptr)
    ##### mm_delete(data_ptr)

    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: mm_delete(foo);

    ### mm_delete_a(array_data_ptr)
    ##### mm_delete_a(array_data_ptr)

    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: mm_delete_a(foo_arr);

    ### mm_null(data)
    ##### mm_null(data)

    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: bool dataIsNull = mm_null(foo);

    ### mm_sizeof(data)
    ##### mm_sizeof(data)

    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_size = mm_sizeof(foo);

    ### mm_count(data)
    ##### mm_count(data)

    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

  18. Nick Chiasson revised this gist May 3, 2016. 1 changed file with 50 additions and 0 deletions.
    50 changes: 50 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,56 @@ I decided to try my hand at making my code a bit safer as far as managing weak r

    I also came up with two seperate static classes which are only really different in that they use two different data structures.

    ## Usage

    - Import the .cpp files into your project source and the .h files into your project headers.
    - Include only the MemMon.h file wherever you plan on using it.
    - Inside of MemMon.h is where you set your desired implementation (map, set, or none).
    - Find the macro definition for MEMMON_TYPE and set it to one of MAPMEMMON_TYPE, SETMEMMON_TYPE, or NULL_MEMMON_TYPE.
    - From now on, instead of new, delete, new[], and delete[] keywords, use mm_new, mm_delete, mm_new_a, and mm_delete_a, respectively.

    ### mm_new(constructor)

    MemMon new expects to be passed a constructor of the type to allocate.

    Example usage: Foo *foo = mm_new(Foo(args));

    ### mm_new_a(type, count)

    MemMon new array expects to be passed a type and the number of elements of that type to allocate.

    Example usage: Foo *foo_arr = mm_new_a(Foo, 25);

    ### mm_delete(data_ptr)

    MemMon delete expects to be passed a pointer to the data to delete.

    Example usage: mm_delete(foo);

    ### mm_delete_a(array_data_ptr)

    MemMon delete array expects to be passed a pointer to the data to delete where the data was allocated as an array.

    Example usage: mm_delete_a(foo_arr);

    ### mm_null(data)

    MemMon null check expects to be passed a pointer to the data to check if that data is valid or null.

    Example usage: bool dataIsNull = mm_null(foo);

    ### mm_sizeof(data)

    MemMon size expects to be passed a pointer to some data and will check how many bytes were allocated to that address. This works effectively on arrays allocated with mm_new_a just as well as single chunks of data allocated with mm_new. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_size = mm_sizeof(foo);

    ### mm_count(data)

    MemMon element count expects to be passed a pointer to some data and will treat that data as an array, checking how many elements were allocated to the array. Note, this macro is really for arrays, but can be used with regular pointers allocated with mm_new - the output in that case will always be 1. This macro is only available with MEMMON_TYPE set to MAPMEMMON_TYPE.

    Example usage: size_t foo_arr_count = mm_count(foo_arr);

    ## SetMemMon

    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. Although the next iteration is more useful, I kept this one around just because of the slight speed compromise.
  19. Nick revised this gist May 3, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions MemMon.h
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    #ifndef MEMMON_H

    #include <SetMemMon.h>
    #include <MapMemMon.h>
    #include "SetMemMon.h"
    #include "MapMemMon.h"

    /**
    * MemMon - Memory monitor
  20. Nick revised this gist May 3, 2016. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    all:
    g++ -o speedtest speedtest.cpp MemMon.cpp SetMemMon.cpp MapMemMon.cpp -std=c++11

    clean:
    rm -f speedtest *.o
  21. Nick revised this gist May 3, 2016. 3 changed files with 10 additions and 4 deletions.
    4 changes: 3 additions & 1 deletion MapMemMon.h
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    #ifndef MAPMEMMON_H
    #define MAPMEMMON_H

    #include <cstdlib>
    #include <type_traits>
    #include <map>

    /**
    @@ -29,7 +31,7 @@
    * MapMemMon delete
    */
    #ifndef _mmm_delete
    #define _mmm_delete(data) MapMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data)
    #define _mmm_delete(data) MapMemMon::Delete<std::remove_reference<decltype(*data)>::type>(data)
    #endif // _mmm_delete

    /**
    6 changes: 4 additions & 2 deletions SetMemMon.h
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    #ifndef SETMEMMON_H
    #define SETMEMMON_H

    #include <cstdlib>
    #include <type_traits>
    #include <set>

    /**
    @@ -29,14 +31,14 @@
    * SetMemMon delete
    */
    #ifndef _smm_delete
    #define _smm_delete(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, false)
    #define _smm_delete(data) SetMemMon::Delete<std::remove_reference<decltype(*data)>::type>(data, false)
    #endif // _smm_delete

    /**
    * SetMemMon delete array
    */
    #ifndef _smm_delete_a
    #define _smm_delete_a(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, true)
    #define _smm_delete_a(data) SetMemMon::Delete<std::remove_reference<decltype(*data)>::type>(data, true)
    #endif // _smm_delete_a

    /**
    4 changes: 3 additions & 1 deletion speedtest.cpp
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,9 @@ int main(int argc, char *argv[])
    printf("\n");
    }

    printf("Done. Press enter.");

    getchar();

    return rc;
    }
    }
  22. Nick Chiasson revised this gist Apr 9, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions speedtest.cpp
    Original file line number Diff line number Diff line change
    @@ -14,8 +14,8 @@ int main(int argc, char *argv[])

    for (int i = 0; i < 100000; ++i)
    {
    int *foo = new int[10000]();
    delete[] foo;
    int *foo = mm_new_a(int ,10000);
    mm_delete_a(foo);
    }
    t_finish = clock() - t_start;

  23. Nick revised this gist Apr 9, 2016. 5 changed files with 265 additions and 107 deletions.
    99 changes: 56 additions & 43 deletions MapMemMon.h
    Original file line number Diff line number Diff line change
    @@ -4,50 +4,60 @@
    #include <map>

    /**
    * MapMemMon new
    */
    #ifndef mmm_new
    #define mmm_new(constructor) MapMemMon::New<decltype(constructor)>(new constructor, 1)
    #endif // mmm_new
    * SetMemMon - Memory monitor using a stl map
    *
    * It is not recommended to use the macros and functions in this file directly.
    * Instead, use MemMon.h and set the MEMMON_TYPE preprocessor definition to
    * MAPMEMMON_TYPE.
    */

    /**
    * MapMemMon new array
    */
    #ifndef mmm_new_a
    #define mmm_new_a(type, n) MapMemMon::New<type>(new type[n](), n)
    #endif // mmm_new_a
    * MapMemMon new
    */
    #ifndef _mmm_new
    #define _mmm_new(constructor) MapMemMon::New<decltype(constructor)>(new constructor, 1)
    #endif // _mmm_new

    /**
    * MapMemMon delete
    */
    #ifndef mmm_delete
    #define mmm_delete(data) MapMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data)
    #endif // mmm_delete
    * MapMemMon new array
    */
    #ifndef _mmm_new_a
    #define _mmm_new_a(type, n) MapMemMon::New<type>(new type[n](), n)
    #endif // _mmm_new_a

    /**
    * MapMemMon null check
    */
    #ifndef mmm_null
    #define mmm_null MapMemMon::Null
    #endif // mmm_null
    * MapMemMon delete
    */
    #ifndef _mmm_delete
    #define _mmm_delete(data) MapMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data)
    #endif // _mmm_delete

    /**
    * MapMemMon memory size
    */
    #ifndef mmm_sizeof
    #define mmm_sizeof(data) MapMemMon::SizeOf((void *)data)
    #endif // mmm_sizeof
    * MapMemMon null check
    */
    #ifndef _mmm_null
    #define _mmm_null MapMemMon::Null
    #endif // _mmm_null

    /**
    * MapMemMon element count
    */
    #ifndef mmm_count
    #define mmm_count(data) mm_sizeof((void *)data)/sizeof(decltype(*data))
    #endif // mmm_count
    * MapMemMon memory size
    */
    #ifndef _mmm_sizeof
    #define _mmm_sizeof(data) MapMemMon::SizeOf((void *)data)
    #endif // _mmm_sizeof

    /**
    * MapMemMon element count
    */
    #ifndef _mmm_count
    #define _mmm_count(data) mm_sizeof((void *)data)/sizeof(decltype(*data))
    #endif // _mmm_count

    class MapMemMon
    {
    public:
    virtual ~MapMemMon() = 0;

    static void Initialize();

    static void Cleanup();
    @@ -102,21 +112,24 @@ inline size_t MapMemMon::Delete(T * data)
    size_t bytesDeleted = 0;
    size_t dataSize = SizeOf(data);
    size_t dataCount = dataSize / sizeof(T);
    if (allocatedMemory != 0)
    if (data != 0)
    {
    allocatedMemory->erase((void *)data);
    bytesDeleted = dataSize;
    if (allocatedMemory->empty()) {
    Cleanup();
    if (allocatedMemory != 0)
    {
    allocatedMemory->erase((void *)data);
    bytesDeleted = dataSize;
    if (allocatedMemory->empty()) {
    Cleanup();
    }
    }
    if (dataCount > 1)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    }
    if (dataCount > 1)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    return bytesDeleted;
    }
    7 changes: 7 additions & 0 deletions MemMon.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    #include "MemMon.h"

    void MemMon::Cleanup()
    {
    SetMemMon::Cleanup();
    MapMemMon::Cleanup();
    }
    143 changes: 143 additions & 0 deletions MemMon.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,143 @@
    #ifndef MEMMON_H

    #include <SetMemMon.h>
    #include <MapMemMon.h>

    /**
    * MemMon - Memory monitor
    *
    * It is recommended to use the macros in this file rather than those in the
    * included files directly.
    */

    #ifndef NULL_MEMMON_TYPE
    #define NULL_MEMMON_TYPE 0
    #endif // NULL_MEMMON_TYPE

    #ifndef SETMEMMON_TYPE
    #define SETMEMMON_TYPE 1
    #endif // SETMEMMON_TYPE

    #ifndef MAPMEMMON_TYPE
    #define MAPMEMMON_TYPE 2
    #endif // MAPMEMMON_TYPE

    /**
    * Use this to set the type of memory monitoring to use.
    */
    #ifndef MEMMON_TYPE
    #define MEMMON_TYPE MAPMEMMON_TYPE
    #endif // MEMMON_TYPE

    /**
    * MemMon new
    */
    #if MEMMON_TYPE==SETMEMMON_TYPE
    #ifndef mm_new
    #define mm_new _smm_new
    #endif
    #elif MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_new
    #define mm_new _mmm_new
    #endif
    #else
    #ifndef mm_new
    #define mm_new(constructor) new constructor
    #endif
    #endif // mm_new

    /**
    * MemMon new array
    */
    #if MEMMON_TYPE==SETMEMMON_TYPE
    #ifndef mm_new_a
    #define mm_new_a _smm_new_a
    #endif
    #elif MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_new_a
    #define mm_new_a _mmm_new_a
    #endif
    #else
    #ifndef mm_new_a
    #define mm_new_a(type, n) new type[n]()
    #endif
    #endif // mm_new_a

    /**
    * MemMon delete
    */
    #if MEMMON_TYPE==SETMEMMON_TYPE
    #ifndef mm_delete
    #define mm_delete _smm_delete
    #endif
    #elif MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_delete
    #define mm_delete _mmm_delete
    #endif
    #else
    #ifndef mm_delete
    #define mm_delete(data) if(data!=0){delete data;data=0;}
    #endif
    #endif // mm_delete

    /**
    * MemMon delete array
    */
    #if MEMMON_TYPE==SETMEMMON_TYPE
    #ifndef mm_delete_a
    #define mm_delete_a _smm_delete_a
    #endif
    #elif MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_delete_a
    #define mm_delete_a _mmm_delete
    #endif
    #else
    #ifndef mm_delete_a
    #define mm_delete_a(data) if(data!=0){delete[] data;data=0;}
    #endif
    #endif // mm_delete_a

    /**
    * MemMon null check
    */
    #if MEMMON_TYPE==SETMEMMON_TYPE
    #ifndef mm_null
    #define mm_null _smm_null
    #endif
    #elif MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_null
    #define mm_null _mmm_null
    #endif
    #else
    #ifndef mm_null
    #define mm_null(data) (data == 0)
    #endif
    #endif // mm_null

    /**
    * MemMon memory size
    */
    #if MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_sizeof
    #define mm_sizeof _mmm_sizeof
    #endif
    #endif // mm_sizeof

    /**
    * MemMon element count
    */
    #if MEMMON_TYPE==MAPMEMMON_TYPE
    #ifndef mm_count
    #define mm_count _mmm_count
    #endif
    #endif // mm_count

    class MemMon
    {
    public:
    virtual ~MemMon() = 0;

    void Cleanup();
    };

    #endif // MEMMON_H
    87 changes: 50 additions & 37 deletions SetMemMon.h
    Original file line number Diff line number Diff line change
    @@ -4,43 +4,53 @@
    #include <set>

    /**
    * SetMemMon new
    */
    #ifndef smm_new
    #define smm_new(constructor) SetMemMon::New<decltype(constructor)>(new constructor, 1)
    #endif // smm_new
    * SetMemMon - Memory monitor using a stl set
    *
    * It is not recommended to use the macros and functions in this file directly.
    * Instead, use MemMon.h and set the MEMMON_TYPE preprocessor definition to
    * SETMEMMON_TYPE.
    */

    /**
    * SetMemMon new array
    */
    #ifndef smm_new_a
    #define smm_new_a(type, n) SetMemMon::New<type>(new type[n](), n)
    #endif // smm_new_a
    * SetMemMon new
    */
    #ifndef _smm_new
    #define _smm_new(constructor) SetMemMon::New<decltype(constructor)>(new constructor, 1)
    #endif // _smm_new

    /**
    * SetMemMon delete
    */
    #ifndef smm_delete
    #define smm_delete(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, false)
    #endif // smm_delete
    * SetMemMon new array
    */
    #ifndef _smm_new_a
    #define _smm_new_a(type, n) SetMemMon::New<type>(new type[n](), n)
    #endif // _smm_new_a

    /**
    * SetMemMon delete array
    */
    #ifndef smm_delete_a
    #define smm_delete_a(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, true)
    #endif // smm_delete_a
    * SetMemMon delete
    */
    #ifndef _smm_delete
    #define _smm_delete(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, false)
    #endif // _smm_delete

    /**
    * SetMemMon null check
    */
    #ifndef smm_null
    #define smm_null SetMemMon::Null
    #endif // smm_null
    * SetMemMon delete array
    */
    #ifndef _smm_delete_a
    #define _smm_delete_a(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, true)
    #endif // _smm_delete_a

    /**
    * SetMemMon null check
    */
    #ifndef _smm_null
    #define _smm_null SetMemMon::Null
    #endif // _smm_null

    class SetMemMon
    {
    public:
    virtual ~SetMemMon() = 0;

    static void Initialize();

    static void Cleanup();
    @@ -90,20 +100,23 @@ inline T * SetMemMon::New(T * data, size_t count)
    template<typename T>
    inline void SetMemMon::Delete(T * data, bool isArray)
    {
    if (allocatedMemory != 0)
    if (data != 0)
    {
    allocatedMemory->erase((void *)data);
    if (allocatedMemory->empty()) {
    Cleanup();
    if (allocatedMemory != 0)
    {
    allocatedMemory->erase((void *)data);
    if (allocatedMemory->empty()) {
    Cleanup();
    }
    }
    if (isArray)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    }
    if (isArray)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    }

    36 changes: 9 additions & 27 deletions speedtest.cpp
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,7 @@
    #include <iostream>
    #include <ctime>

    #include "Foo.h"
    #include "SetMemMon.h"
    #include "MapMemMon.h"
    #include "MemMon.h"

    int main(int argc, char *argv[])
    {
    @@ -12,36 +10,20 @@ int main(int argc, char *argv[])
    for (int i = 0; i < 10; ++i)
    {
    clock_t t_start = clock();
    clock_t t_01 = t_start;
    clock_t t_02 = t_start;
    clock_t t_03 = t_start;
    clock_t t_finish = t_start;

    for (int i = 0; i < 1000; ++i)
    for (int i = 0; i < 100000; ++i)
    {
    Foo *foo = new Foo[1000]();
    int *foo = new int[10000]();
    delete[] foo;
    }
    t_01 = clock() - t_start;
    t_finish = clock() - t_start;

    for (int i = 0; i < 1000; ++i)
    {
    Foo *foo = smm_new_a(Foo, 1000);
    smm_delete_a(foo);
    }
    t_02 = clock() - t_start;

    for (int i = 0; i < 1000; ++i)
    {
    Foo *foo = mmm_new_a(Foo, 1000);
    mmm_delete(foo);
    }
    t_03 = clock() - t_start;

    printf("%d clicks (%f seconds)\n", t_01, ((float)t_01) / CLOCKS_PER_SEC);
    printf("%d clicks (%f seconds)\n", t_02, ((float)t_02) / CLOCKS_PER_SEC);
    printf("%d clicks (%f seconds)\n", t_03, ((float)t_03) / CLOCKS_PER_SEC);
    printf("%d clicks (%f seconds)\n", t_finish, ((float)t_finish) / CLOCKS_PER_SEC);
    printf("\n");
    }


    getchar();

    return rc;
    }
  24. Nick Chiasson revised this gist Apr 8, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,6 @@ Using a map, I stored a pointer to the address as the key and the number of byte

    So for performance testing, among other stress tests, I basically just did a bunch of new array and delete array calls in a loop and compared the clock times with regular new[] and delete[] calls. I would say I am happy enough with the results, given the overhead. Should there be any curiosity, the following is the average of my results for a run of speedtest.cpp:

    - Regular new[] and delete[]: 160 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - Regular new[] and delete[]: 160 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - SetMemMon new[] and delete[]: 370 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - MapMemMon new[] and delete[]: 580 clicks for 1000 allocated and deleted Foo arrays of size 1000
  25. Nick Chiasson revised this gist Apr 8, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ I also came up with two seperate static classes which are only really different

    ## SetMemMon

    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. I although the next iteration is more useful, I kept this one around just because of the slight speed compromise.
    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. Although the next iteration is more useful, I kept this one around just because of the slight speed compromise.

    ## MapMemMon

  26. Nick Chiasson revised this gist Apr 8, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # MemMon
    # MemMon Memory Monitors

    ###### NOT A GARBAGE COLLECTOR

  27. Nick Chiasson renamed this gist Apr 8, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  28. Nick Chiasson created this gist Apr 8, 2016.
    39 changes: 39 additions & 0 deletions MapMemMon.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,39 @@
    #include "MapMemMon.h"

    using namespace std;

    std::map<void *, size_t> * MapMemMon::allocatedMemory = 0;

    void MapMemMon::Initialize()
    {
    if (allocatedMemory == 0)
    {
    allocatedMemory = new std::map<void *, size_t>();
    }
    }

    void MapMemMon::Cleanup()
    {
    if (allocatedMemory != 0)
    {
    delete allocatedMemory;
    allocatedMemory = 0;
    }
    }

    bool MapMemMon::Null(void * address)
    {
    bool rc = (allocatedMemory == 0);
    rc = (!rc ? allocatedMemory->find(address) == allocatedMemory->end() : rc);
    return rc;
    }

    size_t MapMemMon::SizeOf(void * data)
    {
    size_t s = 0;
    if (!Null(data))
    {
    s = (*allocatedMemory)[data];
    }
    return s;
    }
    124 changes: 124 additions & 0 deletions MapMemMon.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,124 @@
    #ifndef MAPMEMMON_H
    #define MAPMEMMON_H

    #include <map>

    /**
    * MapMemMon new
    */
    #ifndef mmm_new
    #define mmm_new(constructor) MapMemMon::New<decltype(constructor)>(new constructor, 1)
    #endif // mmm_new

    /**
    * MapMemMon new array
    */
    #ifndef mmm_new_a
    #define mmm_new_a(type, n) MapMemMon::New<type>(new type[n](), n)
    #endif // mmm_new_a

    /**
    * MapMemMon delete
    */
    #ifndef mmm_delete
    #define mmm_delete(data) MapMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data)
    #endif // mmm_delete

    /**
    * MapMemMon null check
    */
    #ifndef mmm_null
    #define mmm_null MapMemMon::Null
    #endif // mmm_null

    /**
    * MapMemMon memory size
    */
    #ifndef mmm_sizeof
    #define mmm_sizeof(data) MapMemMon::SizeOf((void *)data)
    #endif // mmm_sizeof

    /**
    * MapMemMon element count
    */
    #ifndef mmm_count
    #define mmm_count(data) mm_sizeof((void *)data)/sizeof(decltype(*data))
    #endif // mmm_count

    class MapMemMon
    {
    public:
    static void Initialize();

    static void Cleanup();

    template<typename T>
    static T * New(T * data, size_t count);

    template<typename T>
    static size_t Delete(T * data);

    static bool Null(void * address);

    static size_t SizeOf(void * data);

    private:
    static std::map<void *, size_t> * allocatedMemory;

    };

    template<typename T>
    inline T * MapMemMon::New(T * data, size_t count)
    {
    if (allocatedMemory == 0)
    {
    Initialize();
    }
    if (allocatedMemory != 0 && data != 0 && count > 0)
    {
    (*allocatedMemory)[(void *)data] = sizeof(T) * count;
    }
    else
    {
    if (data != 0)
    {
    if (count > 1)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    data = 0;
    }
    }
    return data;
    }

    template<typename T>
    inline size_t MapMemMon::Delete(T * data)
    {
    size_t bytesDeleted = 0;
    size_t dataSize = SizeOf(data);
    size_t dataCount = dataSize / sizeof(T);
    if (allocatedMemory != 0)
    {
    allocatedMemory->erase((void *)data);
    bytesDeleted = dataSize;
    if (allocatedMemory->empty()) {
    Cleanup();
    }
    }
    if (dataCount > 1)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    return bytesDeleted;
    }

    #endif // MAPMEMMON_H
    23 changes: 23 additions & 0 deletions README
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    # MemMon

    ###### NOT A GARBAGE COLLECTOR

    I decided to try my hand at making my code a bit safer as far as managing weak references goes, so I tried to make something to track references to memory locations. I soon thought that it was a stupid idea and simplified it so that it was simply the memory locations' validity which were being monitored. That way, all I needed to do was essentially a custom null check to see if my weak references were still valid. I tried to do this in the simplest and most aesthetically pleasing way as possible. Naturally, that means (to me) attempting to overload the new and delete keywords for every possible type. Well, since you can't do that, I decided to use macros :)

    I also came up with two seperate static classes which are only really different in that they use two different data structures.

    ## SetMemMon

    This one represents my first iteration on this idea. Using a set, it simply keeps track of which memory locations are still not freed. I although the next iteration is more useful, I kept this one around just because of the slight speed compromise.

    ## MapMemMon

    Using a map, I stored a pointer to the address as the key and the number of bytes to be stored as the value. This way, I could ALSO perform a sizeof on any dynamically allocated arrays, and expanding on that, an element count as well! I am happy with the results and think that I will likely be using MapMemMon all the time in the future.

    ## Testing Results

    So for performance testing, among other stress tests, I basically just did a bunch of new array and delete array calls in a loop and compared the clock times with regular new[] and delete[] calls. I would say I am happy enough with the results, given the overhead. Should there be any curiosity, the following is the average of my results for a run of speedtest.cpp:

    - Regular new[] and delete[]: 160 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - SetMemMon new[] and delete[]: 370 clicks for 1000 allocated and deleted Foo arrays of size 1000
    - MapMemMon new[] and delete[]: 580 clicks for 1000 allocated and deleted Foo arrays of size 1000
    29 changes: 29 additions & 0 deletions SetMemMon.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    #include "SetMemMon.h"

    using namespace std;

    std::set<void *> * SetMemMon::allocatedMemory = 0;

    void SetMemMon::Initialize()
    {
    if (allocatedMemory == 0)
    {
    allocatedMemory = new std::set<void *>();
    }
    }

    void SetMemMon::Cleanup()
    {
    if (allocatedMemory != 0)
    {
    delete allocatedMemory;
    allocatedMemory = 0;
    }
    }

    bool SetMemMon::Null(void * address)
    {
    bool rc = (allocatedMemory == 0);
    rc = (!rc ? allocatedMemory->find(address) == allocatedMemory->end() : rc);
    return rc;
    }
    110 changes: 110 additions & 0 deletions SetMemMon.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,110 @@
    #ifndef SETMEMMON_H
    #define SETMEMMON_H

    #include <set>

    /**
    * SetMemMon new
    */
    #ifndef smm_new
    #define smm_new(constructor) SetMemMon::New<decltype(constructor)>(new constructor, 1)
    #endif // smm_new

    /**
    * SetMemMon new array
    */
    #ifndef smm_new_a
    #define smm_new_a(type, n) SetMemMon::New<type>(new type[n](), n)
    #endif // smm_new_a

    /**
    * SetMemMon delete
    */
    #ifndef smm_delete
    #define smm_delete(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, false)
    #endif // smm_delete

    /**
    * SetMemMon delete array
    */
    #ifndef smm_delete_a
    #define smm_delete_a(data) SetMemMon::Delete<std::remove_reference_t<decltype(*data)>>(data, true)
    #endif // smm_delete_a

    /**
    * SetMemMon null check
    */
    #ifndef smm_null
    #define smm_null SetMemMon::Null
    #endif // smm_null

    class SetMemMon
    {
    public:
    static void Initialize();

    static void Cleanup();

    template<typename T>
    static T * New(T * data, size_t count);

    template<typename T>
    static void Delete(T * data, bool isArray);

    static bool Null(void * address);

    private:
    static std::set<void *> * allocatedMemory;

    };

    template<typename T>
    inline T * SetMemMon::New(T * data, size_t count)
    {
    if (allocatedMemory == 0)
    {
    Initialize();
    }
    if (allocatedMemory != 0 && data != 0 && count > 0)
    {
    allocatedMemory->insert((void *)data);
    }
    else
    {
    if (data != 0)
    {
    if (count > 1)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    data = 0;
    }
    }
    return data;
    }

    template<typename T>
    inline void SetMemMon::Delete(T * data, bool isArray)
    {
    if (allocatedMemory != 0)
    {
    allocatedMemory->erase((void *)data);
    if (allocatedMemory->empty()) {
    Cleanup();
    }
    }
    if (isArray)
    {
    delete[] data;
    }
    else
    {
    delete data;
    }
    }

    #endif // SETMEMMON_H
    47 changes: 47 additions & 0 deletions speedtest.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    #include <iostream>
    #include <ctime>

    #include "Foo.h"
    #include "SetMemMon.h"
    #include "MapMemMon.h"

    int main(int argc, char *argv[])
    {
    int rc = 0;

    for (int i = 0; i < 10; ++i)
    {
    clock_t t_start = clock();
    clock_t t_01 = t_start;
    clock_t t_02 = t_start;
    clock_t t_03 = t_start;

    for (int i = 0; i < 1000; ++i)
    {
    Foo *foo = new Foo[1000]();
    delete[] foo;
    }
    t_01 = clock() - t_start;

    for (int i = 0; i < 1000; ++i)
    {
    Foo *foo = smm_new_a(Foo, 1000);
    smm_delete_a(foo);
    }
    t_02 = clock() - t_start;

    for (int i = 0; i < 1000; ++i)
    {
    Foo *foo = mmm_new_a(Foo, 1000);
    mmm_delete(foo);
    }
    t_03 = clock() - t_start;

    printf("%d clicks (%f seconds)\n", t_01, ((float)t_01) / CLOCKS_PER_SEC);
    printf("%d clicks (%f seconds)\n", t_02, ((float)t_02) / CLOCKS_PER_SEC);
    printf("%d clicks (%f seconds)\n", t_03, ((float)t_03) / CLOCKS_PER_SEC);
    printf("\n");
    }

    return rc;
    }