-
-
Save anonymous/4470980 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <string.h> | |
// WORKSPACE BEISPIEL | |
// FreeBsd Lizenziert | |
// tim glabisch | |
// | |
// Ein Workspace ermöglicht, dass beliebige variablen darin abgelegt werden, der komplette | |
// Workspace kann daraufhin aus dem Ram abgelegt werden. | |
// Varnish nutzt dies beispielsweise damit in (inline C) Plugins speicherplatz über eine WS_MALLOC | |
// Methode beschaffen werden kann. | |
// Varnish hat keine Möglichkeit zu erkennen wann die Variable wieder freigegeben werden kann, | |
// Die Lösung ist einfach: | |
// Der Benutzer muss den Speicher aus einem vorab angelegten Workspace beschaffen, | |
// Dieser Workspace kann nach verarbeitung des Requests gelöscht werden, damit sind Memory-Leaks | |
// nicht mehr möglich. | |
// | |
// Das Beispiel ist mit Valgrind getestet und enthält keine Memory Leaks | |
// | |
// Um das Programm zu testen reicht: | |
// $ gcc -o a.out -g -O0 [FILE].c | |
// Der Eigentliche Workspace enthält einen Void Pointer damit beliebige Daten abgelegt werden | |
// können. Desweiteren wird gespeichert wie groß dieser insgesamt ist, sowie wieviel speicher noch | |
// vorhanden ist | |
typedef struct { | |
void* data; | |
int bytesUsed; | |
int bytesTotal; | |
} ws; | |
// Ein neuer Workspace kann über die Funktion ws_new erstellt werden | |
// als Parameter wird die Anzahl der bytes übergeben welche für den Workspace beitstehen müssen. | |
// Dies entspricht der "größe" des Void-Pointers (data) den der Workspace für die Daten | |
// vorhalten muss | |
ws* ws_new(int bytes) { | |
ws* workspace = (ws*)malloc(sizeof(ws)); | |
workspace->data = (void*)malloc(bytes); | |
workspace->bytesUsed = 0; | |
workspace->bytesTotal = bytes; | |
return workspace; | |
} | |
// ws_free löscht ein ws Objekt aus dem Speicher | |
// erst die Daten, dann das eigentliche Objekt | |
void ws_free(ws* workspace) { | |
free(workspace->data); | |
free(workspace); | |
} | |
// ws_malloc wird aufgerufen um neuen Speicher aus dem Workspace zu holen. | |
// dies funktioniert ähnlich wie die eigentliche malloc funktion, der Speicher wird jedoch | |
// aus dem Workspace geholt. Um Überläufe zu vermeiden muss geprüft werden ob der Workspace groß | |
// genug ist. | |
void* ws_malloc(ws* workspace, int bytes) { | |
if(bytes > workspace->bytesTotal - workspace->bytesUsed) | |
return NULL; | |
void* ret = (void*) workspace->data + workspace->bytesUsed; | |
workspace->bytesUsed = workspace->bytesUsed + bytes; | |
return ret; | |
} | |
int main() { | |
ws* workspace = ws_new(8); | |
char* c1 = (char*)ws_malloc(workspace, 4); | |
strcpy(c1, "abc"); | |
// alloc the first 4 bytes and check if everything works :) | |
assert(strcmp(c1, "abc") == 0); | |
char* c2 = (char*)ws_malloc(workspace, 4); | |
strcpy(c2, "def"); | |
// check the first and the second allocaton | |
assert(strcmp(c1, "abc") == 0); | |
assert(strcmp(c2, "def") == 0); | |
// we just have 8 bytes, no so we couldnt alloc more ... | |
assert(ws_malloc(workspace, 1) == NULL); | |
ws_free(workspace); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment