Library: work out a solution how to store a Deleter functor

After some fruitless attempts, I settled for using std::function directly,
in order to establish a working baseline of this (tremendously complicated)
allocation logic. Storing a std::function in the ArrayBucket is certainly
wasteful (it costs 4 »slots« of memory), but has the upside that
it handles all those tricky corner cases magically; notably
the functor can be stored completely inline in the most relevant
case where the allocator is a monostate; moreover we bind a lambda,
which can be optimised very effectively, so that in the simplest case
there will be only the single indirection through the ''invoker''.

This **completes the code path for a simple usage cycle**

🠲 ''and hooray ... the test crashes with a double-free''
This commit is contained in:
Fischlurch 2024-06-09 23:45:24 +02:00
parent 954a399b1c
commit 8534914c71
3 changed files with 141 additions and 54 deletions

View file

@ -77,6 +77,7 @@ namespace lib {
using util::max;
using util::min;
using util::_Fmt;
using std::is_trivially_destructible_v;
template<class I, template<typename> class ALO>
class ElementFactory
@ -140,13 +141,15 @@ namespace lib {
destroy (ArrayBucket<I>* bucket)
{
REQUIRE (bucket);
size_t cnt = bucket->cnt;
if (not is_trivially_destructible_v<E>)
{
size_t cnt = bucket->cnt;
using ElmAlloT = typename AlloT::template rebind_traits<E>;
auto elmAllo = adaptAllocator<E>();
for (size_t idx=0; idx<cnt; ++idx)
ElmAlloT::destroy (elmAllo, & bucket->subscript(idx));
}
size_t storageBytes = bucket->buffSiz;
using ElmAlloT = typename AlloT::template rebind_traits<E>;
auto elmAllo = adaptAllocator<E>();
for (size_t idx=0; idx<cnt; ++idx)
ElmAlloT::destroy (elmAllo, & bucket->subscript(idx));
std::byte* loc = reinterpret_cast<std::byte*> (bucket);
AlloT::deallocate (baseAllocator(), loc, storageBytes);
};
@ -227,12 +230,6 @@ namespace lib {
return newBucket;
}
*/
// // ensure sufficient storage or verify the ability to re-allocate
// if (not (Coll::hasReserve(sizeof(TY))
// or POL::canExpand(sizeof(TY))
// or handling_.template canDynGrow<TY>()))
// throw err::Invalid{_Fmt{"Unable to accommodate further element of type %s "}
// % util::typeStr<TY>()};
}
void
@ -250,7 +247,7 @@ namespace lib {
Fac::template createAt<E> (tar, idx
,std::move_if_noexcept (src->subscript(idx)));
}
tar->cnt = idx+1; // mark fill continuously for proper clean-up after exception
tar->cnt = idx+1; // mark fill continuously for proper clean-up after exception
}
};
@ -268,16 +265,16 @@ namespace lib {
template<class I, class E>
struct HandlingStrategy
{
enum DestructionMethod { UNKNOWN
, TRIVIAL
, ELEMENT
, VIRTUAL
};
enum DestructionMethod{ UNKNOWN
, TRIVIAL
, ELEMENT
, VIRTUAL
};
static Literal
render(DestructionMethod m)
render (DestructionMethod m)
{
switch (m)
{
{
case TRIVIAL: return "trivial";
case ELEMENT: return "fixed-element-type";
case VIRTUAL: return "virtual-baseclass";
@ -289,6 +286,7 @@ namespace lib {
DestructionMethod destructor{UNKNOWN};
bool lock_move{false};
/** mark that we're about to accept an otherwise unknown type,
* which can not be trivially moved. This irrevocably disables
* relocations by low-level `memove` for this container instance */
@ -306,37 +304,37 @@ namespace lib {
return is_trivially_copyable_v<E> and not lock_move;
}
template<typename TY>
std::function<void(I&)>
selectDestructor()
template<typename TY, class FAC>
typename ArrayBucket<I>::Deleter
selectDestructor (FAC const& factory)
{
if (is_trivially_destructible_v<TY>)
if (is_Subclass<TY,I>() and has_virtual_destructor_v<I>)
{
__ensureMark (TRIVIAL, util::typeStr<TY>());
return [](auto){ /* calmness */ };
__ensureMark<TY> (VIRTUAL);
return [factory](ArrayBucket<I>* bucket){ unConst(factory).template destroy<I> (bucket); };
}
if (is_same_v<TY,E> and is_Subclass<E,I>())
{
__ensureMark (ELEMENT, util::typeStr<TY>());
return [](I& elm){ reinterpret_cast<E&>(elm).~E(); };
__ensureMark<TY> (ELEMENT);
return [factory](ArrayBucket<I>* bucket){ unConst(factory).template destroy<E> (bucket); };
}
if (is_Subclass<TY,I>() and has_virtual_destructor_v<I>)
if (is_trivially_destructible_v<TY>)
{
__ensureMark (VIRTUAL, util::typeStr<TY>());
return [](I& elm){ elm.~I(); };
__ensureMark<TY> (TRIVIAL);
return [factory](ArrayBucket<I>* bucket){ unConst(factory).template destroy<TY> (bucket); };
}
throw err::Invalid{_Fmt{"Unsupported kind of destructor for element type %s."}
% util::typeStr<TY>()};
}
template<typename TY>
void
__ensureMark(DestructionMethod expectedKind, string typeID)
__ensureMark (DestructionMethod expectedKind)
{
if (destructor != UNKNOWN and destructor != expectedKind)
throw err::Invalid{_Fmt{"Unable to handle destructor for element type %s, "
"since this container has been primed to use %s-deleters."}
% typeID % render(expectedKind)};
% util::typeStr<TY>() % render(expectedKind)};
destructor = expectedKind;
}
};
@ -404,9 +402,6 @@ namespace lib {
void
emplaceElm (ARGS&& ...args)
{
// ensure proper configuration of clean-up for the container
auto invokeDestructor = handling_.template selectDestructor<TY>();
// mark when target type is not trivially movable
handling_.template probeMoveCapability<TY>();
@ -416,15 +411,32 @@ namespace lib {
"into container for element size %d."}
% util::typeStr<TY>() % sizeof(TY) % Coll::spread()};
// ensure sufficient storage or verify the ability to re-allocate
if (not (Coll::hasReserve(sizeof(TY))
or POL::canExpand(sizeof(TY))
or not handling_.lock_move))
throw err::Invalid{_Fmt{"Unable to accommodate further element of type %s "}
% util::typeStr<TY>()};
size_t elmSiz = sizeof(TY);
size_t newPos = Coll::size();
size_t newCnt = Coll::empty()? INITIAL_ELM_CNT : newPos+1;
adjustStorage (newCnt, max (elmSiz, Coll::spread()));
ENSURE (Coll::data_);
if (not Coll::data_->deleter)
UNIMPLEMENTED ("setup deleter trampoline");
Coll::data_->cnt = newPos+1;
ensureDeleter<TY>();
POL::template createAt<TY> (Coll::data_, newPos, forward<ARGS> (args)...);
Coll::data_->cnt = newPos+1;
}
template<class TY>
void
ensureDeleter()
{
// ensure clean-up can be handled properly
typename POL::Fac& factory(*this);
typename ArrayBucket<I>::Deleter deleterFunctor = handling_.template selectDestructor<TY> (factory);
if (Coll::data_->deleter) return;
Coll::data_->deleter = deleterFunctor;
}
void

View file

@ -68,6 +68,7 @@
#include "lib/iter-adapter.hpp"
#include <cstddef>
#include <functional>
namespace lib {
@ -84,7 +85,7 @@ namespace lib {
, deleter{nullptr}
{ }
typedef void (*Deleter) (ArrayBucket*);
using Deleter = std::function<void(ArrayBucket*)>;
size_t cnt;
size_t spread;
@ -119,7 +120,7 @@ namespace lib {
destroy()
{
if (deleter)
(*deleter) (this);
deleter (this);
}
};

View file

@ -82032,8 +82032,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="idea"/>
</node>
</node>
<node COLOR="#338800" CREATED="1717710799094" ID="ID_310099304" MODIFIED="1717717678921" TEXT="ObjectFactory">
<linktarget COLOR="#687a8b" DESTINATION="ID_310099304" ENDARROW="Default" ENDINCLINATION="-927;146;" ID="Arrow_ID_1881268863" SOURCE="ID_342640598" STARTARROW="None" STARTINCLINATION="-107;-6;"/>
<node COLOR="#338800" CREATED="1717710799094" ID="ID_310099304" MODIFIED="1717973310165" TEXT="ObjectFactory">
<linktarget COLOR="#687a8b" DESTINATION="ID_310099304" ENDARROW="Default" ENDINCLINATION="-927;146;" ID="Arrow_ID_1881268863" SOURCE="ID_342640598" STARTARROW="None" STARTINCLINATION="-199;-12;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1717710834678" ID="ID_16117383" MODIFIED="1717710852024" TEXT="eine Variation der generischen StdFactory"/>
<node CREATED="1717710923482" ID="ID_1281147725" MODIFIED="1717710954590" TEXT="nur da&#xdf; hier die Instanzen speziell gem&#xe4;&#xdf; Spread und Offset platziert werden m&#xfc;ssen"/>
@ -82274,8 +82274,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1717546408121" ID="ID_1274735212" MODIFIED="1717546425197" TEXT="mu&#xdf; den Allokator mit einbinden">
<node CREATED="1717546597442" ID="ID_1158247490" MODIFIED="1717546607338" TEXT="&#x27f9; Trampolin mu&#xdf; von Allokator erben"/>
<node CREATED="1717546480353" ID="ID_1419974412" MODIFIED="1717546493220" TEXT="Problem : Trampolin f&#xfc;r Allokator-Instanz">
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1717546661817" ID="ID_999124001" MODIFIED="1717546671561" TEXT="wir haben NUR einen Pointer in der Storage vorgesehen">
<node COLOR="#5b280f" CREATED="1717546661817" ID="ID_999124001" MODIFIED="1717980636112" TEXT="wir haben NUR einen Pointer in der Storage vorgesehen">
<icon BUILTIN="messagebox_warning"/>
<icon BUILTIN="button_cancel"/>
</node>
<node COLOR="#435e98" CREATED="1717546728089" ID="ID_549532304" MODIFIED="1717596648356" TEXT="wer verwaltet dann die Allokator-Instanz?">
<icon BUILTIN="help"/>
@ -82302,6 +82303,26 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1717980644190" ID="ID_1561213301" MODIFIED="1717980806813" TEXT="w&#xe4;hle die KISS-L&#xf6;sung: speichere eine std::function im ArrayBucket">
<arrowlink COLOR="#4f3c50" DESTINATION="ID_1548641171" ENDARROW="Default" ENDINCLINATION="239;0;" ID="Arrow_ID_1057786065" STARTARROW="None" STARTINCLINATION="164;59;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
<node CREATED="1717980667483" ID="ID_1900000633" MODIFIED="1717980709406">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
jetzt habe ich mich sowiso schon mal f&#252;r die <i><font color="#5c166e">vorl&#228;ufige Verschwendung</font></i>&#160;entschieden
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1717980713277" ID="ID_445857465" MODIFIED="1717980771913" TEXT="wenn das wirklich ein Problem ist, kann &#x201e;man&#x201c; sp&#xe4;ter immer noch was Kluges machen"/>
</node>
</node>
<node CREATED="1717632428656" ID="ID_798550383" MODIFIED="1717632452224" TEXT="es sind zwei Aufgaben">
<icon BUILTIN="messagebox_warning"/>
@ -82328,12 +82349,49 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font NAME="SansSerif" SIZE="10"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717976409462" ID="ID_1970199405" MODIFIED="1717976419858" TEXT="Darstellung Delter-Trampolin">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1717976432490" ID="ID_1286685499" MODIFIED="1717976455971" TEXT="ein reiner Funktions-Pointer kann keine Instanzen darstellen"/>
<node COLOR="#5b280f" CREATED="1717976482929" ID="ID_185745331" MODIFIED="1717976489323" TEXT="L&#xf6;sung (elaboriert)">
<icon BUILTIN="button_cancel"/>
<node CREATED="1717976543478" ID="ID_542963817" MODIFIED="1717976557846" TEXT="Hilfsklasse mit eingebettetem Instanz-Pointer"/>
<node CREATED="1717976815570" ID="ID_1165477430" MODIFIED="1717976868893" TEXT="dieser zeigt auf einen Allokator-Invoker"/>
<node CREATED="1717976870144" ID="ID_328476311" MODIFIED="1717976896824" TEXT="...der dann entweder statisch oder dynamisch gehalten wird"/>
<node CREATED="1717976897580" ID="ID_446769209" MODIFIED="1717976916653" TEXT="und eine Invoke-Funktion in der Hilfsklasse delegiert an den Invoker"/>
<node COLOR="#5b280f" CREATED="1717976917577" ID="ID_32007559" MODIFIED="1717976942427" TEXT="macht effektiv das Gleiche wie std::function unter -O3">
<icon BUILTIN="stop-sign"/>
<node CREATED="1717976943966" ID="ID_689712327" MODIFIED="1717976954792" TEXT="hab das via Godbolt gepr&#xfc;ft"/>
<node CREATED="1717976955436" ID="ID_1872938427" MODIFIED="1717976987136" TEXT="-O3 &#x27f9; std::function wird ein direkter Funktionspointer-Aufruf (falls einfache Funktion)"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717710755310" ID="ID_342640598" MODIFIED="1717717695572" TEXT="sinnvollerweise mit einer Allocator-Factory hinterlegen">
<arrowlink COLOR="#687a8b" DESTINATION="ID_310099304" ENDARROW="Default" ENDINCLINATION="-927;146;" ID="Arrow_ID_1881268863" STARTARROW="None" STARTINCLINATION="-107;-6;"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1717976462276" ID="ID_1548641171" MODIFIED="1717980806814" TEXT="L&#xf6;sung (KISS) : std::function&lt;void(void*)&gt; speichern">
<arrowlink COLOR="#d6f0fe" DESTINATION="ID_1121455521" ENDARROW="Default" ENDINCLINATION="-145;-3;" ID="Arrow_ID_543216727" STARTARROW="None" STARTINCLINATION="-326;17;"/>
<linktarget COLOR="#4f3c50" DESTINATION="ID_1548641171" ENDARROW="Default" ENDINCLINATION="239;0;" ID="Arrow_ID_1057786065" SOURCE="ID_1561213301" STARTARROW="None" STARTINCLINATION="164;59;"/>
<icon BUILTIN="forward"/>
</node>
<node CREATED="1717977026883" ID="ID_1912003517" MODIFIED="1717977099753" TEXT="Diskussion">
<icon BUILTIN="yes"/>
<node CREATED="1717977030018" ID="ID_152036319" MODIFIED="1717977050524" TEXT="Nachteil std::function : etwas fetterer #include"/>
<node CREATED="1717980381361" ID="ID_957746192" MODIFIED="1717980397198" TEXT="Nachteil std::function belegt 4 &#xbb;slots&#xab; im ArrayBucket">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1717977051599" ID="ID_400259742" MODIFIED="1717977072257" TEXT="Vorteil: std::function managed bereits automatisch die Instanz-Storage falls nicht-trivial "/>
<node CREATED="1717977082019" ID="ID_1627070325" MODIFIED="1717977094246" TEXT="in jedem Fall bekomme ich eine 2-fache Indirektion"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717710755310" ID="ID_342640598" MODIFIED="1717973310165" TEXT="sinnvollerweise mit einer Object-Factory hinterlegen">
<arrowlink COLOR="#687a8b" DESTINATION="ID_310099304" ENDARROW="Default" ENDINCLINATION="-927;146;" ID="Arrow_ID_1881268863" STARTARROW="None" STARTINCLINATION="-199;-12;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1717710901355" ID="ID_718524980" MODIFIED="1717715225349" TEXT="das Meiste ist n&#xe4;mlich generische Boilerplate"/>
<node CREATED="1717715255933" ID="ID_261113900" MODIFIED="1717715273774" TEXT="damit k&#xf6;nnte auch das Thema &#xbb;durchreichen des Basis-Allokators&#xab; generisch gel&#xf6;st werden"/>
<node CREATED="1717980461670" ID="ID_1121455521" MODIFIED="1717980515297" TEXT="speichere direkt eine capture-by-value der Factory/Policy">
<linktarget COLOR="#d6f0fe" DESTINATION="ID_1121455521" ENDARROW="Default" ENDINCLINATION="-145;-3;" ID="Arrow_ID_543216727" SOURCE="ID_1548641171" STARTARROW="None" STARTINCLINATION="-326;17;"/>
<icon BUILTIN="idea"/>
<node CREATED="1717980523492" ID="ID_1804149986" MODIFIED="1717980548838" TEXT="damit macht das Lambda-Framework + std::function die ganze Arbeit"/>
<node CREATED="1717980563305" ID="ID_809590729" MODIFIED="1717980590273" TEXT="wenn der Allocator ein &#xbb;monostate&#xab; ist, dann ist diese Capture-Storage inline"/>
<node CREATED="1717980592211" ID="ID_532129426" MODIFIED="1717980605247" TEXT="aber auch ein einfacher back-Pointer w&#xfc;rde noch inline gespeichert"/>
</node>
</node>
<node CREATED="1717942814818" ID="ID_1746173014" MODIFIED="1717943166752" TEXT="m&#xf6;gliche Arten von Deletern">
<linktarget COLOR="#6172af" DESTINATION="ID_1746173014" ENDARROW="Default" ENDINCLINATION="165;696;" ID="Arrow_ID_28316112" SOURCE="ID_927074944" STARTARROW="None" STARTINCLINATION="-72;-321;"/>
@ -82344,7 +82402,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1717942989115" ID="ID_426648590" MODIFIED="1717943121885" TEXT="element type &#x27f9; invoke Element-destructor (Lock)"/>
</node>
</node>
<node CREATED="1717543083078" ID="ID_530261806" MODIFIED="1717543114805" TEXT="getMover()"/>
<node COLOR="#5b280f" CREATED="1717543083078" ID="ID_530261806" MODIFIED="1717976370468" TEXT="getMover()">
<icon BUILTIN="button_cancel"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717777101317" ID="ID_826816346" MODIFIED="1717777105434" TEXT="konkret einbinden">
@ -82423,7 +82483,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
<node COLOR="#338800" CREATED="1717779506814" ID="ID_584325941" MODIFIED="1717894192704" TEXT="Objekte umkopieren">
<linktarget COLOR="#ec1c03" DESTINATION="ID_584325941" ENDARROW="Default" ENDINCLINATION="167;18;" ID="Arrow_ID_1090340504" SOURCE="ID_184907732" STARTARROW="None" STARTINCLINATION="178;0;"/>
<linktarget COLOR="#339199" DESTINATION="ID_584325941" ENDARROW="Default" ENDINCLINATION="167;18;" ID="Arrow_ID_1090340504" SOURCE="ID_184907732" STARTARROW="None" STARTINCLINATION="178;0;"/>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#435e98" CREATED="1717776994933" ID="ID_916393989" MODIFIED="1717894075291" TEXT="Problem: nicht genau passende Storage">
@ -82431,11 +82491,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1717777049607" ID="ID_184907732" MODIFIED="1717894184170" TEXT="brauche den konkreten Zieltyp hier">
<arrowlink COLOR="#ec1c03" DESTINATION="ID_584325941" ENDARROW="Default" ENDINCLINATION="167;18;" ID="Arrow_ID_1090340504" STARTARROW="None" STARTINCLINATION="178;0;"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717858632242" HGAP="37" ID="ID_230351736" MODIFIED="1717894176693" TEXT="korrekte Methode f&#xfc;r Verschiebung w&#xe4;hlen" VSHIFT="28">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1717777049607" ID="ID_184907732" MODIFIED="1717980968358" TEXT="brauche den konkreten Zieltyp hier">
<arrowlink COLOR="#339199" DESTINATION="ID_584325941" ENDARROW="Default" ENDINCLINATION="167;18;" ID="Arrow_ID_1090340504" STARTARROW="None" STARTINCLINATION="178;0;"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1717858632242" HGAP="52" ID="ID_230351736" MODIFIED="1717980953018" TEXT="korrekte Methode f&#xfc;r Verschiebung w&#xe4;hlen" VSHIFT="62">
<icon BUILTIN="button_ok"/>
<node CREATED="1717894097677" ID="ID_296210161" MODIFIED="1717894105895" TEXT="entweder memmove"/>
<node CREATED="1717894106512" ID="ID_1351589328" MODIFIED="1717894141182">
<richcontent TYPE="NODE"><html>
@ -82451,6 +82511,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</richcontent>
</node>
</node>
<node COLOR="#435e98" CREATED="1717980924344" ID="ID_599080738" MODIFIED="1717980947745" TEXT="L&#xf6;sung: auch die AllocationPolicy zus&#xe4;tzlich auf E templaten">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1717894127145" ID="ID_774641997" MODIFIED="1717894180642" TEXT="andere F&#xe4;lle werden nicht zugelassen">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1717894315160" ID="ID_1788527715" MODIFIED="1717894325877" TEXT="auf welcher Ebene wird das gepr&#xfc;ft?">
@ -82468,6 +82531,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1717980838451" ID="ID_123345043" MODIFIED="1717980849735" TEXT="hab es jetzt vorerst doch wieder dorthin geschoben"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717980850354" ID="ID_1951694568" MODIFIED="1717980857530" TEXT="TODO: bessere L&#xf6;sung finden">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node CREATED="1717894410331" ID="ID_732905043" MODIFIED="1717894437670" TEXT="es gen&#xfc;gt, die move_lock-Flag zu pr&#xfc;fen">
<icon BUILTIN="idea"/>
@ -82976,6 +83043,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716857382440" ID="ID_46730448" MODIFIED="1716857402102" TEXT="simpleUsage">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1717980996623" ID="ID_644007892" MODIFIED="1717981004874" TEXT="Several mit drei Zahlen"/>
<node CREATED="1717981006247" ID="ID_1037000737" MODIFIED="1717981014900" TEXT="wieder darauf zugreifen (subscript)">
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1717981016452" ID="ID_406273640" MODIFIED="1717981023372" STYLE="fork" TEXT="double free">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="broken-line"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716857382441" ID="ID_748929457" MODIFIED="1716857402102" TEXT="check_Builder">
<icon BUILTIN="flag-yellow"/>