GARANTIR DESCONTO

Fórum Invalid Pointer Operation ao tentar liberar um objeto #423677

15/09/2012

0

Estou tendo o erro de invid pointer operation ao tentar liberar um objeto

este objeto implementa uma interface, e ao finalizar o processo tento liberar este objeto da memoria e da este erro

alguém sabe me dizer como faço pra resolver isso?

obrigado.
Rafael Reis

Rafael Reis

Responder

Posts

17/09/2012

Marco Salles

Sim é isto...

So que usar freeandnil para ambos .. Em algumas das vezes o free tb é suficiente


Responder

Gostei + 0

18/09/2012

Alisson Santos

Marcos creio que se ele utilizar apenas o free não vai ser liberado o ponteiro da memória, creio que tenha que utilizar o FreeAndNil, pois ele tanto libera o objeto da memória como o ponteiro.
No caso ele não utilizar o Create(Self), sendo assim teria que utilizar o FreeAndNil.
Eu sempre aconselho a utilizar esse comando, pois terá a certeza que o objeto está destruido e limpo a memória.
Responder

Gostei + 0

18/09/2012

Marco Salles

Marcos creio que se ele utilizar apenas o free não vai ser liberado o ponteiro da memória, creio que tenha que utilizar o FreeAndNil, pois ele tanto libera o objeto da memória como o ponteiro.
No caso ele não utilizar o Create(Self), sendo assim teria que utilizar o FreeAndNil.
Eu sempre aconselho a utilizar esse comando, pois terá a certeza que o objeto está destruido e limpo a memória.


Ponteiro é apenas algo que aponta para um endereço da memória . Neste endereço pode ter algo aproveitavel ou pode ter lixo
Quando vc utiliza o Freeandnil , vc ao "testar" o ponteiro , vc consegue identificar que este ponteiro aponta para
um endereço inexistente . Mas quem libera Recursos , quem libera memória definitivamente é o Free

faça um simples teste

coloque a instrução ReportMemoryLeaksOnShutdown:=true; no dpr para gerenciar a memória

coloque tres botões e execute separadamente o seguinte evento onclick

coloque

procedure TForm1.Button1Click(Sender: TObject);
var
lista:TStrings;
i:integer;
begin
for i:=0 to 10 do
  begin
  lista:=TStringList.Create;
  Lista.free;
end;
end;


procedure TForm1.Button2Click(Sender: TObject);
var
lista:TStrings;
i:integer;
begin
for i:=0 to 10 do
  begin
  lista:=TStringList.Create;
  FreeAndNil(lista);
end;
end;



//Aqui sim tem Vazamento de memória
procedure TForm1.Button3Click(Sender: TObject);
var
lista:TStrings;
i:integer;
begin
for i:=0 to 10 do
  begin
  lista:=TStringList.Create;
end;
end;


Responder

Gostei + 0

18/09/2012

Alisson Santos

Marcos referente aos teste é realmente, mais o que eu queria dizer é que ainda fica com o ponteiro, e o udeal é utilizar o freeandnil para tirar o ponteiro e limpa a memória.
O free realmente faz a limpeza, mais ele não elimina o ponteiro.
Responder

Gostei + 0

18/09/2012

Deivison Melo

Podemos dar o tópico como encerrado?
Responder

Gostei + 0

18/09/2012

Marco Salles

Marcos referente aos teste é realmente, mais o que eu queria dizer é que ainda fica com o ponteiro, e o udeal é utilizar o freeandnil para tirar o ponteiro e limpa a memória.
O free realmente faz a limpeza, mais ele não elimina o ponteiro.


Olha so , isto não é o caso e nem um pouco tão mais importante . o importante é o free

vou te dar um exemplo

var
lista:TStrings;
i:integer;
begin

if lista = nil then
 showmessage('Mas Eu não estou utilizando o FreeanNil ???'+sLineBreak+
             'Porque este Ponteiro Não foi Limpo ?????');
lista:=TStringList.Create;
FreeAndNil(lista);
end;
Responder

Gostei + 0

18/09/2012

Alisson Santos

Obrigado pelas explicações, é que eu tinha outro conceito. Mais com o dialogo me deu uma outra visão.
Responder

Gostei + 0

18/09/2012

Alisson Santos

Obrigado pelas explicações, é que eu tinha outro conceito. Mais com o dialogo me deu uma outra visão.
Responder

Gostei + 0

18/09/2012

Marco Salles

claro , nos estamos ai para isto . Mas veja não se pode negar a importancia do freeandNil , devemos tirar proveito dele

veja esta situação

//variavel local fora do evento.. Ok ??
var
Lista:Tstrings;


dentro de um botão

if lista = nil then // tem que cria-la
lista:=TstringList.create;
//Vamos utiliza-la
lista.add('Na segunda Vez vai dar ponteiro Inválido');
showmessage(Lista.Strings[0]);
Lista.free;
end;

Tai um exemplo que devemos utilizar freeandNil ... Não para liberar Recuros , mas para instanciar o objeto , porque
do jeito que esta o Ponteiro vai apontar para um endereço que contem Lixo

depois oara entender o propósito , faça o mesmo teste utilizando o FreeandNil

if lista = nil then // tem que cria-la
lista:=TstringList.create;
//Vamos utiliza-la
lista.add('Na segunda Vez vai dar ponteiro Inválido');
showmessage(Lista.Strings[0]);
Lista.free;
end;

[]sds



Responder

Gostei + 0

18/09/2012

Rafael Reis

Valeu galera, muito obrigado pela ajuda.

pra mim ficou bem claro.

até a próxima
Responder

Gostei + 0

25/09/2012

Rafael Reis

Pessoal, aproveitando o mesmo assunto.

Eu estou criando um componente, onde o mesmo tem uma propriedade chamada DataSource que é do tipo TList, onde eu passo uma lista de qualquer objeto, e eu o populo lendo esta lista de objeto


sabem me dizer por qual motivo eu não consigo destruir esta lista quando eu destruo o componente? se eu tento destruir o componente, da erro de invalid pointer, se eu não destruo quando fecho a aplicação dá o mesmo erro. Abaixo segue o código fonte do componete.

acho que ainda não entendi muito bem como o delphi trabalha com essa questão de referência de memória.
Se puderem me ajudar mais uma vez, ficarei grato. Obrigado.



unit RCheckListBox;

interface

uses
  System.SysUtils, System.Classes, Vcl.Controls, Vcl.StdCtrls, Vcl.CheckLst, Generics.Collections, RTTI;

type
  TRCheckListBox = class(TCheckListBox)
  private
    FDescriptionName: String;
    FMandatoryField: boolean;
    FDataSource: TList;
    FPersistentField: boolean;
    FFieldName: String;
    FIDName: String;
    FListValue: TStrings;
    function GetValue: String;
    procedure SetDataSource(const Value: TList);
    procedure SetDescriptionName(const Value: String);
    procedure SetFieldName(const Value: String);
    procedure SetIDName(const Value: String);
    procedure SetMandatoryField(const Value: boolean);
    procedure SetPersistentField(const Value: boolean);
    procedure SetValue(const Value: String);
    procedure SetListValue(const Value: TStrings);
    { Private declarations }
  protected
    { Protected declarations }
  published
    property FieldName:String read FFieldName write SetFieldName;
    property MandatoryField: boolean read FMandatoryField write SetMandatoryField;
    property PersistentField: boolean read FPersistentField write SetPersistentField;
    property IDFieldName:String read FIDName write SetIDName;
    property DescriptionFieldName:String read FDescriptionName write SetDescriptionName;
    property ListValue: TStrings read FListValue write SetListValue;
  public

    property DataSource:TList read FDataSource write SetDataSource;
    property Value:String read GetValue write SetValue;
    procedure FindIndexByIDFieldName(idFieldNameValue: string);
    procedure DataBind;
    function GetObject<T: class>:T;
    function GetCheckedObjects: TList;

    constructor Create(AOwner: TComponent);override;
    destructor destroy;

  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('SIATD', [TRCheckListBox]);
end;

{ TRCheckListBox }

constructor TRCheckListBox.Create(AOwner: TComponent);
begin
  inherited;
  self.FListValue := TStringList.Create;
end;

procedure TRCheckListBox.DataBind;
var
  i:integer;
  context: TRttiContext;
  prop: TRttiProperty;
begin
  self.Clear;
  if (self.FDataSource <> nil)  or (self.FListValue <> nil) then
  begin
      if self.FDataSource <> nil then
      begin
        for i := 0 to self.FDataSource.Count-1 do
        begin
           prop := context.GetType(TObject(self.FDataSource[i]).ClassType).GetProperty(self.FDescriptionName);
           self.Items.Add(prop.GetValue(TObject(self.FDataSource[i])).ToString);
        end;
      end
      else
      if self.FListValue <> nil then
      begin
        for I := 0 to self.FListValue.Count-1 do
        begin
          self.Items.Add(self.FListValue.Names[I])
        end;
      end;

      if self.Items.Count > 0 then self.ItemIndex := 0;
  end;

end;

destructor TRCheckListBox.destroy;
var
  i:integer;
begin
  for I := 0 to FDataSource.Count-1 do   ////...>>>> aqui que dá o erro
     FreeAndNil(TObject(FDataSource[i]))

  FreeAndNil(FDataSource);

  inherited Destroy;
end;

procedure TRCheckListBox.FindIndexByIDFieldName(idFieldNameValue: string);
var
  I:integer;
  context: TRttiContext;
  prop: TRttiProperty;
begin
   if Assigned(FDataSource) then
   begin
       for i := 0 to FDataSource.Count-1 do
       begin
          prop := context.GetType(TObject(FDataSource[i]).ClassType).GetProperty(self.IDFieldName);
          if  Pos(prop.GetValue(TObject(FDataSource[i])).ToString, idFieldNameValue ) > 0 then
              Self.Checked[I] := true
          else
             Self.Checked[I] := false;
       end;
   end
   else
   begin
       for I := 0 to self.Items.Count-1 do
       begin
           if FListValue.Count > 0 then
           begin
               if  Pos(self.FListValue.ValueFromIndex[I], idFieldNameValue ) > 0 then
                    Self.Checked[I] := true
               else
                    Self.Checked[I] := false;

           end
           else
           begin
               if  Pos(self.Items[I], idFieldNameValue ) > 0 then
                    Self.Checked[I] := true
               else
                    Self.Checked[I] := false;

           end;
       end;
   end;
end;

function TRCheckListBox.GetCheckedObjects: TList;
var
 i:integer;
 list:Tlist;
begin
  if FDataSource <> nil then
  begin
      list := TList.Create;
      for i := 0 to FDataSource.Count-1 do
      begin
        if self.Checked[I] then
            list.Add(TObject(DataSource[i]));
      end;
      result := list;
  end else result := nil;
end;

function TRCheckListBox.GetObject<T>: T;
begin
    if (FDataSource <> nil) and (self.Checked[self.GetItemIndex]) then
        Result :=  T(TObject(FDataSource[self.GetItemIndex]));
end;

function TRCheckListBox.GetValue: String;
var
  ind:integer;
  context: TRttiContext;
  prop: TRttiProperty;
  val: string;
  I: Integer;
begin
    val := EmptyStr;
    if Self.FDataSource = nil then
    begin
       for I := 0 to self.Items.Count-1 do
       begin
           if self.Checked[I] then
           begin
               if self.FListValue.Count = 0 then
                 val := val + self.Items[i]+','
               else
                 val := val + self.FListValue.ValueFromIndex[I]+',';
           end;
       end;
       System.Delete(val,System.Length(val),1);
       result := val;
    end
    else
    begin
       for I := 0 to self.FDataSource.Count-1 do
       begin
           if self.Checked[I] then
           begin
               prop := context.GetType(TObject(Self.FDataSource[I]).ClassType).GetProperty(self.IDFieldName);
               val := val + prop.GetValue(TObject(Self.FDataSource[I])).ToString+',';
           end;
       end;
       System.Delete(val,System.Length(val),1);
       result := val;
    end;
end;

procedure TRCheckListBox.SetDataSource(const Value: TList);
begin
  FDataSource := Value;
end;

procedure TRCheckListBox.SetDescriptionName(const Value: String);
begin
  if FDescriptionName <> Value then
    FDescriptionName := Value;
end;

procedure TRCheckListBox.SetFieldName(const Value: String);
begin
  if FFieldName <> Value then
    FFieldName := Value;
end;

procedure TRCheckListBox.SetIDName(const Value: String);
begin
   if FIDName <> Value then
    FIDName := Value;
end;

procedure TRCheckListBox.SetListValue(const Value: TStrings);
begin
  if FListValue <> Value then
    FListValue.Assign(Value);
end;

procedure TRCheckListBox.SetMandatoryField(const Value: boolean);
begin
  if FMandatoryField <> Value then
    FMandatoryField := Value;
end;

procedure TRCheckListBox.SetPersistentField(const Value: boolean);
begin
  if FPersistentField <> Value then
    FPersistentField := Value;
end;

procedure TRCheckListBox.SetValue(const Value: String);
begin
    self.FindIndexByIDFieldName(Value);
end;

end.

Responder

Gostei + 0

25/09/2012

Alisson Santos

O que ele retorna para você de informação nessa linha de erro.??
Responder

Gostei + 0

25/09/2012

Rafael Reis

O que ele retorna para você de informação nessa linha de erro.??


então dá este erro de invalid Pointer Operation.

e se eu comento esta parte, o erro ocorre quando eu fecho a aplicação. Conseguir ser claro?
Responder

Gostei + 0

27/09/2012

Rafael Reis

E ai pessoal, ninguém?
Responder

Gostei + 0

27/09/2012

Rafael Reis

O problema todo é quando eu passo essa lista por referencia entre os forms, o Delphi parece que se perde, e não consegue destruir essa lista.


Qual seria a melhor forma de se fazer isso no Delphi?

Por exemplo

eu crio uma lista
lista := Tlist.create;

e passo para um outro form essa lista por referencia

ou seja, form2.lista := lista

ai na hora de destruir ele se perde.
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar