Hallo liebe Community
ich habe ein problem mit einem speichermanager. weil ich viele kleine
speicherblöcke regelmäßig anfordere und freigebe, habe ich mir einen
eigenen geschrieben, der den speicher nicht sofort zurückgibt sondern
nur als frei markiert
das ganze wird in einem großen char* array mithilfe einer doppelt verketteten liste gespeichert:
|
Quellcode
|
1
2
3
4
5
6
|
/------------------------------------------------------\
|listinfo|USERDATA| |listinfo|USERDATA| |
\------------------------------------------------------/
^
|
mem
|
der speicherblock 'mem' enthält immer einige listendaten
|
C-/C++-Quelltext
|
1
2
3
4
5
|
struct node
{
unsigned size;
node *next, *last;
};
|
und direkt danach die benutzerdaten.
ein hilfszeiger 'p' zeigt immer auf den ersten knoten der in diesem
speicher liegt.
um einen bereich zu löschen hänge ich einfach die beiden zeiger um,
diese funktion sollte funktioniern
der code:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
void *alloc(unsigned size)
{
if (!mem)
return 0;
if (!p)
// noch kein startknoten angelegt
{
if ((size + sizeof(node)) > memsize)
return 0;
p = reinterpret_cast<node *>(mem); // knoten am begin des blocks erzeugen
p->size = size;
p->last = 0;
p->next = 0;
return p + 1; // benutzerdaten stehen hinter den listeninformationen
}
else
{
if ((reinterpret_cast<char *>(p) - mem) >= (size + sizeof(node)))
// wenn zwischen dem ersten knoten und dem begin des blocks noch platz ist...
{
node *temp = reinterpret_cast<node *>(mem);
temp->size = size;
temp->last = 0;
temp->next = p;
p->last = temp;
p = temp;
return p + 1;
}
else
// <HIER MUSS DER FEHLER LIEGEN ======================================>
{
node *a = p;
node *b = p->next;
while (b)
// bis zum ende der liste suchen
{
if ((reinterpret_cast<char *>(b) - reinterpret_cast<char *>(a) - a->size - sizeof(node)) >= (size + sizeof(node)))
// wenn zwischen 2 noch platz ist
{
node *temp = reinterpret_cast<node *>(reinterpret_cast<char *>(a) + a->size + sizeof(node));
temp->size = size;
temp->next = b;
temp->last = a;
a->next = temp;
b->last = temp;
return temp + 1;
}
b = b->next;
}
unsigned used = (reinterpret_cast<char *>(a) - mem) + a->size + sizeof(node);
if ((used + size + sizeof(node)) > memsize)
return 0;
node *temp = reinterpret_cast<node *>(reinterpret_cast<char *>(a) + a->size + sizeof(node));
temp->size = size;
temp->next = 0;
temp->last = a;
a->next = temp;
return temp + 1;
}
// </HIER MUSS DER FEHLER LIEGEN ======================================>
}
}
void dealloc(void *ptr)
{
node *n = reinterpret_cast<node *>(ptr) - 1; // listeninfos sind vor den benutzerdaten
if (n->next)
{
if (n->last)
{
n->last->next = n->next;
n->next->last = n->last;
}
else
n->next->last = 0;
}
else
{
if (n->last)
n->last->next = 0;
else
p = 0;
}
}
//.................
char *mem; // der speicherblock
unsigned memsize; // gesammtgröße des speicherblocks 'mem'
node *p; // startknoten, zeigt auf das erste element in der liste
|
das '+1' bei der rückgabe liegt daran, dass der allokierte speicher
genau nach den listendaten liegt, also 'sizeof(node)' bytes weiter.
der fehler:
wenn ich mehrere objekte allokiere, scheinen sich einige speicher
bereiche zu überlappen. komischerweise stürzt er jedoch nicht ab
obwohl dabei ja auch die listendaten überschrieben werden müssten.
ein einzelnes element zu erstellen klappt ohne probleme und im debugger
konnte ich auch keine üperlappenden berieche finden.
der große speicherblock wird auch korrekt erzeugt
hoffe einer findet den fehler :cry: