Pour le plaisir de ne pas utiliser Copy dans un code que j'ai fait ce matin (je fais une DLL pour un partenaire, où j'utilise volontairement le moins de lib que possible, donc je réinvente de deux-trois trucs que j'ai déjà écrit comme une persistance objet mais en version ultra ligth), j'ai bidouillé un truc, et j'aimerais savoir ce que vous en pensez et aussi éclairer ma lanterne ...
j'ai plusieurs tableau constants qui ont cette forme, ils ont juste des tailles différentes ...
j'ai un objet ancêtre à mes objets, qui mappent des propriétés publiés et des champs dans une table, j'ai donc
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 const PROPERTIES_MAPPING_xxx: array[0..17] of TPropertyMapping = ( (PropertyName: 'p1'; FieldName: 'f1'; ), (PropertyName: 'p2'; FieldName: 'f2'; ), ... );
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 TSearchObject = class(TPersistent) private FPropertiesMapping: array of TPropertyMapping; protected procedure LoadFromDataSet(ADataSet: TDataSet);Vous noterez donc que l'ancêtre utilise FPropertiesMapping, le tableau dynamique, donc voilà, c'est juste que ce tableau n'est initialisé uniquement (et obligatoirement) par les descendants de TSearchObject ... dans une surcharge du constructeur ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 procedure TSearchObject.LoadFromDataSet(ADataSet: TDataSet); var I: Integer; Field: TField; PropertyValue: Variant; begin for I := Low(FPropertiesMapping) to High(FPropertiesMapping) do begin Field := ADataSet.FindField(FPropertiesMapping[I].FieldName); if Assigned(Field) then begin if Field.IsNull then begin PropertyValue := Null; end else begin if Field.DataType = ftDate then PropertyValue := Field.AsDateTime else PropertyValue := Field.AsString; end; TEpcRTTIWrapper.SetPropertyValue(Self, FPropertiesMapping[I].PropertyName, PropertyValue); end else raise ENeoScopeLADAPIError.Create(ERR_SEARCH_INVALID_DB_MAPPING); end; end;
dans l'ancêtre, évidemment, je nettoye mon tableau dynamique bidonné, sinon gare au dégat
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 constructor THeritedObject.Create(APointer: Pointer); begin .... Pointer(FPropertiesMapping) := @PROPERTIES_MAPPING_HERITED; PInteger(Integer(FPropertiesMapping) - 4)^ := Length(PROPERTIES_MAPPING_HERITED); end;
Alors voici enfin ma question, si je mets que l'affectation à nil (sans la modif de la longueur), et bien, pas de violation d'accès dans l'immédiat mais un comportement assez ératique de mon programme par la suite (le Connect de mon TMyConnection fait une violation d'accès, c'est tombé sur lui va savoir pourquoi ...)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 destructor TSearchObject.Destroy(); begin PInteger(Integer(FPropertiesMapping) - 4)^ := 0; FPropertiesMapping := nil; ... end;
Si je met que l'affectation de la longueur (sans le nil), ben cela semble fonctionner,
si je mets les deux, cela semble aussi fonctionner, et ça me rassure même si je ne sais pas si cela fait grand chose ...
Alors est-ce que l'affectation à nil est utile ou pas ? ou pire était dangereuse puisque cela appele DynArrayClear ?
EDIT : autre question sur une éventulle fuite mémoire, en théorie FPropertiesMapping celui créé par l'instanciation de l'objet n'est qu'une coquille vide ? il n'a pas d'élément donc ne pointe sur aucune zone mémoire, la seule mémoire consommée est le compteur de référence et la longueur du tableau, et le pointeur lui même bien sur ... donc normalement c'est libéré ! non ?
Partager