Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
jasminaorlowska committed Jun 20, 2023
0 parents commit f9432ea
Show file tree
Hide file tree
Showing 10 changed files with 687 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
19 changes: 19 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"macFrameworkPath": [
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/opt/homebrew/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-arm64"
}
],
"version": 4
}
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}
27 changes: 27 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc kompiluj aktywny plik",
"command": "/opt/homebrew/bin/gcc",
"args": [
"-Wall", "-Wextra", "-Wno-implicit-fallthrough", "-std=gnu17", "-fPIC", "-O2",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Zadanie wygenerowane przez debuger."
}
],
"version": "2.0.0"
}
196 changes: 196 additions & 0 deletions malloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
#ifndef _MALLOC_H
#define _MALLOC_H 1

#ifdef _LIBC
#include <features.h>
#endif

#if defined(__STDC__) || defined(__cplusplus)
#include <stddef.h>
#define __malloc_ptr_t void *
#else
#undef size_t
#define size_t unsigned int
#undef ptrdiff_t
#define ptrdiff_t int
#define __malloc_ptr_t char *
#endif

#ifdef _LIBC
/* Used by GNU libc internals. */
#define __malloc_size_t size_t
#define __malloc_ptrdiff_t ptrdiff_t
#elif !defined __attribute_malloc__
#define __attribute_malloc__
#endif

#ifdef __GNUC__

/* GCC can always grok prototypes. For C++ programs we add throw()
to help it optimize the function calls. But this works only with
gcc 2.8.x and egcs. */
#if defined __cplusplus && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 8)
#define __THROW throw()
#else
#define __THROW
#endif
#define __MALLOC_P(args) args __THROW
/* This macro will be used for functions which might take C++ callback
functions. */
#define __MALLOC_PMT(args) args

#else /* Not GCC. */

#define __THROW

#if (defined __STDC__ && __STDC__) || defined __cplusplus

#define __MALLOC_P(args) args
#define __MALLOC_PMT(args) args

#else /* Not ANSI C or C++. */

#define __MALLOC_P(args) () /* No prototypes. */
#define __MALLOC_PMT(args) ()

#endif /* ANSI C or C++. */

#endif /* GCC. */

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((__malloc_ptr_t)0)
#endif
#endif

#ifdef __cplusplus
extern "C"
{
#endif

/* Allocate SIZE bytes of memory. */
extern __malloc_ptr_t malloc __MALLOC_P((size_t __size)) __attribute_malloc__;

/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern __malloc_ptr_t calloc __MALLOC_P((size_t __nmemb, size_t __size))
__attribute_malloc__;

/* Re-allocate the previously allocated block in __ptr, making the new
block SIZE bytes long. */
extern __malloc_ptr_t realloc __MALLOC_P((__malloc_ptr_t __ptr,
size_t __size))
__attribute_malloc__;

/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free __MALLOC_P((__malloc_ptr_t __ptr));

/* Free a block allocated by `calloc'. */
extern void cfree __MALLOC_P((__malloc_ptr_t __ptr));

/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern __malloc_ptr_t memalign __MALLOC_P((size_t __alignment, size_t __size));

/* Allocate SIZE bytes on a page boundary. */
extern __malloc_ptr_t valloc __MALLOC_P((size_t __size)) __attribute_malloc__;

/* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up
__size to nearest pagesize. */
extern __malloc_ptr_t pvalloc __MALLOC_P((size_t __size))
__attribute_malloc__;

/* Underlying allocation function; successive calls should return
contiguous pieces of memory. */
extern __malloc_ptr_t(*__morecore) __MALLOC_PMT((ptrdiff_t __size));

/* Default value of `__morecore'. */
extern __malloc_ptr_t __default_morecore __MALLOC_P((ptrdiff_t __size))
__attribute_malloc__;

/* SVID2/XPG mallinfo structure */

struct mallinfo
{
int arena; /* non-mmapped space allocated from system */
int ordblks; /* number of free chunks */
int smblks; /* number of fastbin blocks */
int hblks; /* number of mmapped regions */
int hblkhd; /* space in mmapped regions */
int usmblks; /* maximum total allocated space */
int fsmblks; /* space available in freed fastbin blocks */
int uordblks; /* total allocated space */
int fordblks; /* total free space */
int keepcost; /* top-most, releasable (via malloc_trim) space */
};

/* Returns a copy of the updated current mallinfo. */
extern struct mallinfo mallinfo __MALLOC_P((void));

/* SVID2/XPG mallopt options */
#ifndef M_MXFAST
#define M_MXFAST 1 /* maximum request size for "fastbins" */
#endif
#ifndef M_NLBLKS
#define M_NLBLKS 2 /* UNUSED in this malloc */
#endif
#ifndef M_GRAIN
#define M_GRAIN 3 /* UNUSED in this malloc */
#endif
#ifndef M_KEEP
#define M_KEEP 4 /* UNUSED in this malloc */
#endif

/* mallopt options that actually do something */
#define M_TRIM_THRESHOLD -1
#define M_TOP_PAD -2
#define M_MMAP_THRESHOLD -3
#define M_MMAP_MAX -4
#define M_CHECK_ACTION -5

/* General SVID/XPG interface to tunable parameters. */
extern int mallopt __MALLOC_P((int __param, int __val));

/* Release all but __pad bytes of freed top-most memory back to the
system. Return 1 if successful, else 0. */
extern int malloc_trim __MALLOC_P((size_t __pad));

/* Report the number of usable allocated bytes associated with allocated
chunk __ptr. */
extern size_t malloc_usable_size __MALLOC_P((__malloc_ptr_t __ptr));

/* Prints brief summary statistics on stderr. */
extern void malloc_stats __MALLOC_P((void));

/* Record the state of all malloc variables in an opaque data structure. */
extern __malloc_ptr_t malloc_get_state __MALLOC_P((void));

/* Restore the state of all malloc variables from data obtained with
malloc_get_state(). */
extern int malloc_set_state __MALLOC_P((__malloc_ptr_t __ptr));

/* Called once when malloc is initialized; redefining this variable in
the application provides the preferred way to set up the hook
pointers. */
extern void(*__malloc_initialize_hook) __MALLOC_PMT((void));
/* Hooks for debugging and user-defined versions. */
extern void(*__free_hook) __MALLOC_PMT((__malloc_ptr_t __ptr,
__const __malloc_ptr_t));
extern __malloc_ptr_t(*__malloc_hook) __MALLOC_PMT((size_t __size,
__const __malloc_ptr_t));
extern __malloc_ptr_t(*__realloc_hook) __MALLOC_PMT((__malloc_ptr_t __ptr,
size_t __size,
__const __malloc_ptr_t));
extern __malloc_ptr_t(*__memalign_hook) __MALLOC_PMT((size_t __alignment,
size_t __size,
__const __malloc_ptr_t));
extern void(*__after_morecore_hook) __MALLOC_PMT((void));

/* Activate a standard set of debugging hooks. */
extern void __malloc_check_init __MALLOC_P((void));

#ifdef __cplusplus
}; /* end of extern "C" */
#endif

#endif /* malloc.h */
Binary file added memory_tests
Binary file not shown.
113 changes: 113 additions & 0 deletions memory_tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "memory_tests.h"
#include <errno.h>
#include "malloc.h"
#include <stdbool.h>
#include <stddef.h>

// Ten plik musi kompilowany z opcjami -std=gnu17 i -fPIC,
// a linkowany z opcjami -Wl,--wrap=malloc -Wl,--wrap=calloc -Wl,--wrap=realloc
// -Wl,--wrap=reallocarray -Wl,--wrap=free -Wl,--wrap=strdup -Wl,--wrap=strndup.

// Przechwytujemy funkcje alokujące i zwalniające pamięć.
void *__real_malloc(size_t size) __attribute__((weak));
void *__real_calloc(size_t nmemb, size_t size) __attribute__((weak));
void *__real_realloc(void *ptr, size_t size) __attribute__((weak));
void *__real_reallocarray(void *ptr, size_t nmemb, size_t size) __attribute__((weak));
char *__real_strdup(const char *s) __attribute__((weak));
char *__real_strndup(const char *s, size_t size) __attribute__((weak));
void __real_free(void *ptr) __attribute__((weak));

// Trzymamy globalnie informacje o alokacjach i zwolnieniach pamięci.
static memory_test_data_t test_data;

// To jest prosty akcesor potrzebny do testowania.
memory_test_data_t *get_memory_test_data(void)
{
return &test_data;
}

// To jest prosty akcesor potrzebny do testowania.
char const *get_magic_string(void)
{
static char const *magic = "quite long magic string";
return magic;
}

// W zadanym momencie alokacja pamięci zawodzi.
static bool should_fail(void)
{
return ++test_data.call_counter == test_data.fail_counter;
}

// Realokacja musi się udać, jeśli nie zwiększamy rozmiaru alokowanej pamięci.
static bool can_fail(void const *old_ptr, size_t new_size)
{
if (old_ptr == NULL)
return true;
else
return new_size > malloc_usable_size((void *)old_ptr);
}

// Symulujemy brak pamięci.
#define UNRELIABLE_ALLOC(ptr, size, fun, name) \
do \
{ \
test_data.call_total++; \
if (ptr != NULL && size == 0) \
{ \
/* Takie wywołanie realloc jest równoważne wywołaniu free(ptr). */ \
test_data.free_counter++; \
return fun; \
} \
void *p = can_fail(ptr, size) && should_fail() ? NULL : (fun); \
if (p) \
{ \
test_data.alloc_counter += ptr != p; \
test_data.free_counter += ptr != p && ptr != NULL; \
} \
else \
{ \
errno = ENOMEM; \
test_data.function_name = name; \
} \
return p; \
} while (0)

void *__wrap_malloc(size_t size)
{
UNRELIABLE_ALLOC(NULL, size, __real_malloc(size), "malloc");
}

void *__wrap_calloc(size_t nmemb, size_t size)
{
UNRELIABLE_ALLOC(NULL, nmemb * size, __real_calloc(nmemb, size), "calloc");
}

void *__wrap_realloc(void *ptr, size_t size)
{
UNRELIABLE_ALLOC(ptr, size, __real_realloc(ptr, size), "realloc");
}

void *__wrap_reallocarray(void *ptr, size_t nmemb, size_t size)
{
UNRELIABLE_ALLOC(ptr, nmemb * size, __real_reallocarray(ptr, nmemb, size), "reallocarray");
}

char *__wrap_strdup(const char *s)
{
UNRELIABLE_ALLOC(NULL, 0, __real_strdup(s), "strdup");
}

char *__wrap_strndup(const char *s, size_t size)
{
UNRELIABLE_ALLOC(NULL, 0, __real_strndup(s, size), "strndup");
}

// Zwalnianie pamięci zawsze się udaje. Odnotowujemy jedynie fakt zwolnienia.
void __wrap_free(void *ptr)
{
test_data.call_total++;
__real_free(ptr);
if (ptr)
test_data.free_counter++;
}
21 changes: 21 additions & 0 deletions memory_tests.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef MEMORY_TESTS_H
#define MEMORY_TESTS_H

// To jest struktura przechowująca informacje o operacjach na pamięci.
// Nie pozwalamy kompilatorowi optymalizować operacji na tych wartościach.
typedef struct {
volatile unsigned call_total; // licznik wszystkich wywołań funkcji
volatile unsigned call_counter; // licznik wywołań alokacji
volatile unsigned fail_counter; // numer błędnej alokacji
volatile unsigned alloc_counter; // liczba wykonanych alokacji
volatile unsigned free_counter; // liczba wykonanych zwolnień
volatile char *function_name; // nazwa nieudanej funkcji
} memory_test_data_t;

// Zapewnia dostęp do wyżej zdefiniowanej struktury.
memory_test_data_t * get_memory_test_data(void);

// Daje wskaźnik na unikalny napis.
char const * get_magic_string(void);

#endif
Loading

0 comments on commit f9432ea

Please sign in to comment.