init
This commit is contained in:
commit
656f82237a
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2018 Muresan Vlad Mihail
|
||||
Contact Info muresanvladmihail@gmail.com, murii@tilde.team
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software.
|
||||
Shall you use this software in a product, an acknowledgment and the
|
||||
contact info(if there is any) of the author(s) must be placed in
|
||||
the product documentation.
|
||||
2. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
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, TITLE
|
||||
AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
|
||||
BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,12 @@
|
|||
CFLAGS=-std=c89 -g -lm -Wall -Wextra -I.
|
||||
|
||||
CC=gcc
|
||||
|
||||
OBJ=example.o mlc.o
|
||||
|
||||
all: $(OBJ)
|
||||
$(CC) $(OBJ) -o example $(CFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f example *.o
|
|
@ -0,0 +1,63 @@
|
|||
About
|
||||
====
|
||||
mlc(memory leak counter) is wrote in C89 and it's not thread safe.
|
||||
It is used mostly in debbuging when you want to know if your C/C++ application has memory leaks, how many, what line and what file(s).
|
||||
|
||||
Usage
|
||||
=======
|
||||
```
|
||||
#include "mlc.h"
|
||||
|
||||
#define MLC_CHECK_FOR_ERRORS
|
||||
|
||||
int main(void) {
|
||||
|
||||
mlc_init();
|
||||
|
||||
char *a = mlc_malloc(126);
|
||||
char *b = mlc_calloc(2, 2);
|
||||
char *c = mlc_malloc(128);
|
||||
|
||||
a = mlc_realloc(a, 64);
|
||||
|
||||
printf("Current memory usage: %zu bytes\n", mlc_usage());
|
||||
printf("Size of 'a' variable's allocation: %zu bytes\n", mlc_size(a));
|
||||
|
||||
mlc_free(c);
|
||||
mlc_free(a);
|
||||
|
||||
mlc_dump(stdout);
|
||||
|
||||
mlc_destroy();
|
||||
printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Authors
|
||||
=======
|
||||
Murii (Muresan Vlad Mihail)
|
||||
|
||||
License
|
||||
=======
|
||||
Copyright (c) 2018 Muresan Vlad Mihail
|
||||
Contact Info muresanvladmihail@gmail.com, murii@tilde.team
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software.
|
||||
Shall you use this software in a product, an acknowledgment and the
|
||||
contact info(if there is any) of the author(s) must be placed in
|
||||
the product documentation.
|
||||
2. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
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, TITLE
|
||||
AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
|
||||
BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright (c) 2018 Muresan Vlad Mihail
|
||||
Contact Info muresanvladmihail@gmail.com, murii@tilde.team
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software.
|
||||
Shall you use this software in a product, an acknowledgment and the
|
||||
contact info(if there is any) of the author(s) must be placed in
|
||||
the product documentation.
|
||||
2. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
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, TITLE
|
||||
AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
|
||||
BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MLC_CHECK_FOR_ERRORS
|
||||
|
||||
#include "mlc.h"
|
||||
|
||||
int main(void) {
|
||||
|
||||
mlc_init();
|
||||
|
||||
char *a = mlc_malloc(32);
|
||||
char *b = mlc_calloc(2, 96);
|
||||
char *c = mlc_malloc(128);
|
||||
|
||||
a = mlc_realloc(a, 64);
|
||||
|
||||
printf("Current memory usage: %zu bytes\n", mlc_usage());
|
||||
printf("Size of 'a' variable's allocation: %zu bytes\n", mlc_size(a));
|
||||
|
||||
mlc_free(c);
|
||||
mlc_free(a);
|
||||
|
||||
mlc_dump(stdout);
|
||||
|
||||
mlc_destroy();
|
||||
printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
Copyright (c) 2018 Muresan Vlad Mihail
|
||||
Contact Info muresanvladmihail@gmail.com, murii@tilde.team
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software.
|
||||
Shall you use this software in a product, an acknowledgment and the
|
||||
contact info(if there is any) of the author(s) must be placed in
|
||||
the product documentation.
|
||||
2. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
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, TITLE
|
||||
AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
|
||||
BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "vector.h"
|
||||
|
||||
#include "mlc.h"
|
||||
|
||||
typedef struct {
|
||||
const char* file; /* file in which the allocation happened */
|
||||
size_t line; /* line at which the allocation happened */
|
||||
size_t size; /* the size of allocated object */
|
||||
char free; /* 1-> free, 0-> not free yet */
|
||||
void* ptr; /* the actual object which is allocated */
|
||||
} alloc_struct;
|
||||
|
||||
|
||||
static vec_t* elements_v; /* holds all allocated structures */
|
||||
|
||||
|
||||
void mlc_init()
|
||||
{
|
||||
elements_v = vec_init(sizeof(void*));
|
||||
}
|
||||
|
||||
|
||||
void mlc_destroy()
|
||||
{
|
||||
vec_destroy(elements_v);
|
||||
}
|
||||
|
||||
|
||||
static void add_structure(void* ptr, size_t obj_size, const char* file, unsigned line)
|
||||
{
|
||||
alloc_struct* ns = malloc(sizeof(alloc_struct));
|
||||
if (!ns)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_ERRORS
|
||||
fprintf(stderr, "Couldn't allocate mlc structure: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
ns->file = file;
|
||||
ns->line = line;
|
||||
ns->size = obj_size;
|
||||
ns->ptr = ptr;
|
||||
ns->free = 0;
|
||||
|
||||
vec_append(elements_v, ns);
|
||||
}
|
||||
|
||||
|
||||
static long has_structure(void* ptr)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < vec_size(elements_v))
|
||||
{
|
||||
alloc_struct *str = (alloc_struct*)vec_get(elements_v, i);
|
||||
if (str->ptr == ptr)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void* _mlc_malloc(size_t size, const char* file, unsigned line)
|
||||
{
|
||||
void* ptr = malloc(size);
|
||||
if (!ptr)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_ERRORS
|
||||
fprintf(stderr, "Couldn't allocate: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#ifdef MLC_ACT_NORMAL
|
||||
return ptr;
|
||||
#endif
|
||||
add_structure(ptr, size, file, line);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void* _mlc_calloc(size_t nitems, size_t size, const char* file, unsigned line)
|
||||
{
|
||||
void* ptr = calloc(nitems, size);
|
||||
if (!ptr)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_ERRORS
|
||||
fprintf(stderr, "Couldn't allocate: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#ifdef MLC_ACT_NORMAL
|
||||
return ptr;
|
||||
#endif
|
||||
add_structure(ptr, size, file, line);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void* _mlc_realloc(void* ptr, size_t size, const char* file, unsigned line)
|
||||
{
|
||||
#ifdef MLC_ACT_NORMAL
|
||||
void* _ptr = realloc(ptr, size);
|
||||
if (!_ptr)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_ERRORS
|
||||
fprintf(stderr, "Couldn't reallocate: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
return _ptr;
|
||||
#endif
|
||||
|
||||
void* _ptr = realloc(ptr, size);
|
||||
alloc_struct* as = NULL;
|
||||
size_t index = 0;
|
||||
if (!_ptr)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_ERRORS
|
||||
fprintf(stderr, "Couldn't reallocate: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index = has_structure(ptr);
|
||||
as = (alloc_struct*)vec_get(elements_v, index);
|
||||
|
||||
if (!as)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_WARNINGS
|
||||
fprintf(stdout, "Reallocating is happening on a NULL ptr %s %u\n", file, line);
|
||||
#endif
|
||||
add_structure(_ptr, size, file, line);
|
||||
}
|
||||
else
|
||||
{
|
||||
as->ptr = _ptr;
|
||||
as->size = size;
|
||||
}
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
|
||||
void _mlc_free(void* ptr, const char* file, unsigned line)
|
||||
{
|
||||
#ifdef MLC_ACT_NORMAL
|
||||
free(ptr);
|
||||
#endif
|
||||
alloc_struct* as = NULL;
|
||||
size_t index = 0;
|
||||
if (ptr == NULL)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_WARNINGS
|
||||
fprintf(stderr, "Couldn't free object: %s, line %u %s \n", file, line, " because it's NULL");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
index = has_structure(ptr);
|
||||
if (index < 0)
|
||||
return;
|
||||
as = (alloc_struct*)vec_get(elements_v, index);
|
||||
if (!as)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_WARNINGS
|
||||
fprintf(stderr, "Invalid free: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
as->free = 1;
|
||||
}
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
|
||||
size_t _mlc_size(void* ptr, const char* file, unsigned line)
|
||||
{
|
||||
alloc_struct* _ptr = (alloc_struct*)vec_get(elements_v, has_structure(ptr));
|
||||
if (!ptr)
|
||||
{
|
||||
#ifdef MLC_CHECK_FOR_WARNINGS
|
||||
fprintf(stderr, "Bad pointer: %s, line %u\n", file, line);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return _ptr->size;
|
||||
}
|
||||
|
||||
|
||||
size_t mlc_usage()
|
||||
{
|
||||
#ifdef MLC_ACT_NORMAL
|
||||
return 0;
|
||||
#endif
|
||||
size_t usage = 0;
|
||||
size_t i = 0;
|
||||
while (i < vec_size(elements_v))
|
||||
{
|
||||
alloc_struct* ptr = ((alloc_struct*)vec_get(elements_v, i));
|
||||
if (ptr->free == 0)
|
||||
usage += ptr->size;
|
||||
i++;
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
|
||||
void mlc_dump(FILE* file)
|
||||
{
|
||||
#ifdef MLC_ACT_NORMAL
|
||||
return;
|
||||
#endif
|
||||
alloc_struct* curr = NULL;
|
||||
size_t i = 0;
|
||||
size_t size = vec_size(elements_v);
|
||||
|
||||
if (!file)
|
||||
file = stdout;
|
||||
|
||||
if (size == 0)
|
||||
fprintf(file, "MLC: no memory leaks! \n");
|
||||
|
||||
while (i < size)
|
||||
{
|
||||
curr = vec_get(elements_v, i);
|
||||
if (curr->free == 0)
|
||||
fprintf(file, "MLC: Unfreed: %p %s, line %zu\n", curr->ptr, curr->file, curr->line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright (c) 2018 Muresan Vlad Mihail
|
||||
Contact Info muresanvladmihail@gmail.com, murii@tilde.team
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software.
|
||||
Shall you use this software in a product, an acknowledgment and the
|
||||
contact info(if there is any) of the author(s) must be placed in
|
||||
the product documentation.
|
||||
2. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
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, TITLE
|
||||
AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
|
||||
BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MLC_H
|
||||
#define MLC_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* 0.1.2 - changed license. If #MLC_ACT_NORMAL, if defined it will make mlc work like
|
||||
normal malloc/calloc etc
|
||||
* 0.1.0 - initial commit
|
||||
* 0.1.1 - better management & performance
|
||||
*/
|
||||
#define MLC_VERSION 0.1.2
|
||||
|
||||
#define mlc_malloc(size) _mlc_malloc(size, __FILE__, __LINE__)
|
||||
#define mlc_calloc(nitems, size) _mlc_calloc(nitems, size, __FILE__, __LINE__)
|
||||
#define mlc_realloc(ptr, size) _mlc_realloc(ptr, size, __FILE__, __LINE__)
|
||||
#define mlc_size(ptr) _mlc_size(ptr, __FILE__, __LINE__)
|
||||
#define mlc_free(ptr) _mlc_free(ptr, __FILE__, __LINE__)
|
||||
|
||||
void mlc_init();
|
||||
void mlc_destroy();
|
||||
void* _mlc_malloc(size_t size, const char* file, unsigned line);
|
||||
void* _mlc_calloc(size_t nitems, size_t size, const char* file, unsigned line);
|
||||
void* _mlc_realloc(void* ptr, size_t size, const char* file, unsigned line);
|
||||
void _mlc_free(void* ptr, const char* file, unsigned line);
|
||||
size_t _mlc_size(void* ptr, const char* file, unsigned line);
|
||||
size_t mlc_usage();
|
||||
void mlc_dump(FILE* file);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* Copyright (c) 2014 Christopher Swenson.
|
||||
* Copyright (c) 2017-2018 Muresan Vlad Mihail
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to aerx and MasterGeek_ for pointing out and solving the issue if capacity is 1
|
||||
* Capacity is set to a hard coded value of 8 because after doing tests that seems
|
||||
* to be the best optimal value, performance wise.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
void** arr;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} vec_t;
|
||||
|
||||
/* type: char*,int,short,float, etc */
|
||||
static __inline vec_t* vec_init(size_t type_size)
|
||||
{
|
||||
vec_t* vec;
|
||||
vec = malloc(sizeof(vec_t));
|
||||
|
||||
vec->capacity = 8;
|
||||
vec->arr = malloc(type_size * vec->capacity);
|
||||
vec->size = 0;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
static __inline void vec_append(vec_t* vec, void* elt)
|
||||
{
|
||||
if (vec->size == vec->capacity)
|
||||
{
|
||||
vec->capacity += vec->capacity | 1; /* Increase capacity by 100% and be sure it's >= than 1 */
|
||||
vec->arr = realloc(vec->arr, vec->capacity * sizeof(elt));
|
||||
if (!vec->arr)
|
||||
printf("Error: Could not realloc in vec_append! \n");
|
||||
}
|
||||
|
||||
vec->arr[vec->size++] = elt;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE
|
||||
* Not bounds safe!
|
||||
*/
|
||||
static __inline void vec_set(vec_t* vec, size_t index, void* value)
|
||||
{
|
||||
vec->arr[index] = value;
|
||||
}
|
||||
|
||||
static __inline void* vec_get(vec_t* vec, size_t i)
|
||||
{
|
||||
return vec->arr[i];
|
||||
}
|
||||
|
||||
static __inline void* vec_pop(vec_t* vec)
|
||||
{
|
||||
return vec->arr[vec->size--];
|
||||
}
|
||||
|
||||
static __inline void vec_del(vec_t* vec, size_t i, size_t type_size)
|
||||
{
|
||||
if (i == vec->size) {
|
||||
vec_pop(vec);
|
||||
} else {
|
||||
memmove(&(vec->arr[i]), &(vec->arr[i + 1]),
|
||||
type_size * vec->size - i - 1);
|
||||
vec->size--;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline size_t vec_size(vec_t* vec)
|
||||
{
|
||||
return vec->size;
|
||||
}
|
||||
|
||||
static __inline void vec_destroy(vec_t* vec)
|
||||
{
|
||||
free(vec->arr);
|
||||
free(vec);
|
||||
}
|
||||
|
||||
#undef VECTOR_TYPE
|
Loading…
Reference in New Issue