PDA

Ver la Versión Completa : Asignar memoria


doctorhd
06-05-2015, 06:54:51
Holas, tengo la siguiente duda, he creado un record con la siguiente estructura:

type
TClaveValor = record
private
FClave:string;
FValueDefault:Variant;
FValue:Variant;
FTipo:TEnumTypeData;
procedure SetClave(const Value:string);
procedure SetValueDefault(const Value:variant);
procedure SetValue(const Value:variant);
procedure SetTipo(const Value:TEnumTypeData);
public
property Clave: string read FClave write SetClave;
property ValueDefault: Variant read FValueDefault write SetValueDefault;
property Value:Variant read FValue write SetValue;
property Tipo: TEnumTypeData read FTipo write SetTipo;
end;

A su vez he creado un tipo que apunta a dicho record:
type PClaveValor = ^TClaveValor;{Puntero a TClaveValor}
Estas estructuras las utilizo para crear elementos en otra clase:

type ArrayPClaveValor = array of PClaveValor;{array de punteros a PClaveValor}

type
TParamRegWin = class
private
FParams:ArrayPClaveValor;
function getParam(const Index: Integer): PClaveValor;
procedure setParam(const Index: Integer; const Value: PClaveValor);
function getCount:Integer;
....
public
constructor Create;
destructor Destroy; override;
procedure AddParam(const AClave:string; const AValueDefault:Variant;AValue:Variant; const ATipo:TEnumTypeData);
....
public
property Param[const Index: Integer]:PClaveValor read getParam write setParam;
property Params:ArrayPClaveValor read FParams write FParams;
property Count:Integer read getCount;
end;

El problema se suscita al crear un nuevo elemento, el cual lo realizo en el procedure AddParam:

procedure TParamRegWin.AddParam(const AClave:string; const AValueDefault:Variant;AValue:Variant; const ATipo:TEnumTypeData);
var vElementos:integer; vPParam:PClaveValor;
begin
vElementos:=Length(FParams);
Setlength(FParams,vElementos+1);{Dimencionamos el tamaño de la lista de campos}
New(vPParam);
vPParam.Clave:=AClave;
vPParam.ValueDefault:=AValueDefault;
vPParam.Value:=AValue;
vPParam.Tipo:=ATipo;
FParams[vElementos]:=vPParam;
end;{procedure}

Como veran utilizo el comando NEW para asignar la memoria al nuevo objeto, el cual cumple su función, pero antes de llegar a utilizar New utilice:
vPParam:=System.AllocMem(SizeOf(TClaveData));
Pero su utilización hacia que se borrara parte del contenido de variables que no participaban dentro del procedure, también probé:
GetMen(vPParam,SizeOf(TClaveData));
Pero también tuve problemas, en la asignación de los valores al puntero.
Mi pregunta es AllocMem y GetMen hacen asignación de memoria disponible o asignan memoria de la que primero encuentran, ya que de acuerdo a las pruebas realizadas, ambos métodos interfieren con la memoria utilizada por otras variables o componentes asignados con anterioridad....Y por ultimo que diferencia existe entre estos dos métodos y el comando NEW...

Saludos....

ecfisa
06-05-2015, 10:12:20
Hola doctorhd.

...
Mi pregunta es AllocMem y GetMen hacen asignación de memoria disponible o asignan memoria de la que primero encuentran, ya que de acuerdo a las pruebas realizadas, ambos métodos interfieren con la memoria utilizada por otras variables o componentes asignados con anterioridad....Y por ultimo que diferencia existe entre estos dos métodos y el comando NEW...

Saludos....
AllocMem y GetMem hacen uso, de ser posible, de la memoria disponible en el heap. No utilizan la primera memoria que encuentran, de otro modo su uso sería un tormento y el autor un perverso. :)

La diferencia entre la función AllocMem y el procedimiento GetMem es que el primero inicializa la memoria asignada y el segundo no. Debido a esto último GetMem es mas eficiente en velocidad (pero a veces es necesaria la inicializacion).

New difiere de los anteriores en que no es necesario indicarle el tamaño a de memoria a asignar, pero no puede manejar un tamaño arbitrario de memoria.

Unos ejemplos muy sencillos de cada uno:

// AllocMem
var
buffer: PChar;
s : string;
begin
s := 'usando AllocMem'+#0;
try
// AllocMem inicializa la memoria asignada con ceros 0
buffer := AllocMem(Length(s));
ShowMessage(buffer); // cadena vacia
StrPCopy(buffer, s);
ShowMessage(buffer);
finally
FreeMem(buffer);
end;
end;

// GetMem
var
buffer: PChar;
s : string;
begin
s := 'usando GetMem'+#0;
try
// GetMem no inicializa la memoria asignada
GetMem(buffer, Length(s));
ShowMessage(buffer); // basura
StrPCopy(buffer, s);
ShowMessage(buffer);
finally
FreeMem(buffer);
end;
end;


// New
procedure TForm1.btnNewClick(Sender: TObject);
type
PReg = ^TReg;
TReg = record
dato1: PChar;
dato2: Integer;
//...
end;
var
pr: PReg;
s : string;
begin
s := 'usando New'+#0;
pr := nil;
try
// New no inicializa la memoria asignada
New(pr);
ShowMessage(Format('%s %d',[pr.dato1, pr.dato2])); // basura
GetMem(pr.dato1, Length(s));
StrPCopy(pr.dato1,s);
pr.dato2 := 1397;
ShowMessage(Format('%s %d',[pr.dato1, pr.dato2]));
finally
FreeMem(pr.dato1);
Dispose(pr);
end;
end;


Saludos :)

nlsgarcia
06-05-2015, 10:18:54
doctorhd,


...¿AllocMem y GetMen hacen asignación de memoria disponible o asignan memoria de la que primero encuentran?...

:rolleyes:

AllocMem, GetMen y New solo asignan bloques de memoria que estén disponibles, en caso de no encontrar la memoria requerida, ocurre una excepción de tipo EOutOfMemory pero en ningún caso se sobrescriben bloques de memoria que estén siendo utilizados.

Revisa esta información

1- System.AllocMem Function (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_AllocMem.html)

2- System.GetMem Function (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_GetMem.html)

3- System.New Function (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_New.html)

4- System.ReallocMem Function (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_ReallocMem.html)

5- AllocMem and GetMem Failure (http://stackoverflow.com/questions/25413302/allocmem-and-getmem-failure)
Espero sea útil :)

Nelson.