This commit is contained in:
Murii 2018-11-14 19:15:55 +02:00
commit 656f82237a
7 changed files with 546 additions and 0 deletions

19
License.md Normal file
View File

@ -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.

12
Makefile Normal file
View File

@ -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

63
README.md Normal file
View File

@ -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.

53
example.c Normal file
View File

@ -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;
}

258
mlc.c Normal file
View File

@ -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++;
}
}

53
mlc.h Normal file
View File

@ -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

88
vector.h Normal file
View File

@ -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