GARANTIR DESCONTO

Fórum Problema com PChar #289292

24/07/2005

0

Ao executar esta rotina ela dá erro em System.LoadResString
procedure TForm1.Button3Click(Sender: TObject);
var
  strRes: PChar;
begin
  try
    strRes := StrAlloc(Length(Edit1.Text)+1);
    strRes := TrataNomeP(PChar(Edit1.Text));
    Edit2.Text := StrPas(strRes);
  finally
    StrDispose(strRes);
  end;
end;

function TrataNomeP(strNome : PChar) : PChar;
{Devolve o strNome sem os conectivos (dos, das, do, da, e, etc.) presentes no arquivo conectivos.txt

entra JOSE DOS SANTOS DA SILVEIRA DE ALMEIDA E SOUZA

sai JOSE SANTOS SILVEIRA ALMEIDA SOUZA    }


const
  ESPACO : array [0..1] of char = ´ ´ + 0 ;
  MAX_BUFFER = 81; //igual ao campo NOME no BD + 1
var
  ptrPos : PChar;
  strPedaco, strNomeComp : array [0..MAX_BUFFER] of char;
begin
  if (strNome = ´´) or (StrLen(strNome) > MAX_BUFFER) then
    exit;
  strNome := AnsiStrLower(strNome);
  ptrPos := AnsiStrPos(strNome, ´ ´);
  strNomeComp := ´´;
  while (ptrPos <> nil) do
  begin
     StrLCopy(strPedaco, strNome, StrLen(strNome) - StrLen(ptrPos));
      // Conectivos é uma TStringList
     if (Conectivos.IndexOf(string(strPedaco)) = -1) then
     begin
       StrCat(strNomeComp, strPedaco);
       StrCat(strNomeComp, ESPACO);
     end;
     repeat //LTrim;
       inc(ptrPos);
     until ptrPos <> ´ ´;
     strNome := ptrPos;
     ptrPos := AnsiStrPos(strNome, ´ ´);
  end;
  StrCat(strNomeComp, strNome);
  StrLCopy(strNome, strNomeComp, StrLen(strNomeComp));
  Result := strNome;
end;


Executando passo-a-passo verifiquei que a rotina TrataNomeP faz o que se espera mas ao atribuir o resultado para strRes, tem um caracter estranho (em forma de um quadradinho) e quando vai copiar para o Edit2.Text dá o erro

´access violation at 0x00405e19: write of adress0x00030d2c. Process Stopped. Use Step Run to continue´


e o compilador para na linha

SetString(Result, Buffer, LoadString(FindResourceHInstance(ResStringRec.Module^), ResStringRec.Identifier, Buffer, SizeOf(Buffer)))


da função LoadResString de System.pas

alguém sabe o que pode pode estar errado :?:

Observei que se o nome for pequeno (JOSE DOS SANTOS por exemplo) o erro não acontece.

A função tem que ser em PChar pois é para uma dll (depois de resolvido este problema).


Uso Delphi 5 e Win XP Pro

Grato


José Henrique

José Henrique

Responder

Posts

26/07/2005

Beppe

Parei de ler seu código quando vi que tu tava usando PChar livremente no seu código. NÃO FAÇA ISSO! Embora PChar te deixa acessar dados como string, elas NÃO SÃO strings. Use o tipo string para isso, que faz alocação implícita de memória.

Se quer saber pq não se deve usar livremente, é devido ao uso errôneo que feaz dela. Por exemplo, vc aloca memória e joga para strRes. Depois perde a referência a ela atribuíndo novamente a strRes, invés de copiar a memória para o endereço já determinado.


Responder

Gostei + 0

26/07/2005

José Henrique

Beppe,
Não me abandone!!!

A função tem que usar PChar pois é para usar em uma dll (que será usada em outras ambientes)

Me indique o que está errado e como posso resolver, por favor!!

Tenho noção que ponteiro é um apontador (termos que alguns acadêmicos acham mais apropriado) para o endereço da memória onde ´começa´ a informação.


Responder

Gostei + 0

27/07/2005

Kapak

Vc está mandando o ponteiro de Edit1.Text e:
     strNome := ptrPos; // Aqui vc perde a referência
E:
  StrLCopy(strNome, strNomeComp, StrLen(strNomeComp)); // Aqui vc não tem mais memória alocada p/ strNome

Então tente substituir:
  StrLCopy(strNome, strNomeComp, StrLen(strNomeComp)); 
  Result := strNome;
Por:
  Result := StrAlloc(StrLen(strNomeComp)+1); // Aqui vc aloca memória p/ Result e libera após chamar a função
  StrLCopy(Result, strNomeComp, StrLen(strNomeComp));

Na chamada da função:
  try 
    strRes := StrAlloc(Length(Edit1.Text)+1); // Não deve ser alocada a memória pq a função já faz isto
    strRes := TrataNomeP(PChar(Edit1.Text)); 
    Edit2.Text := StrPas(strRes); 
  finally 
    StrDispose(strRes);
  end;
Então substitua:
  try
    strRes := TrataNomeP(PChar(Edit1.Text));
    Edit2.Text := StrPas(strRes);
  finally
    StrDispose(strRes);
  end;



Responder

Gostei + 0

27/07/2005

José Henrique

kapak,
Fiz as alterações que você sugeriu e deu certo. Hoje entendo mais de PChar que antes deste post graças a vc e ao Beppe.
Obrigado :D


Responder

Gostei + 0

28/07/2005

Beppe

[quote:1e48cfe51e=´José Henrique´]A função tem que usar PChar pois é para usar em uma dll (que será usada em outras ambientes)[/quote:1e48cfe51e]
E geralmente é a maneira apropriada de se lidar com strings em diferentes linguagens. Mas o que deve ser PChar é apenas a interface, implemente usando o tipo string fornecido pela linguagem.

Dois exemplos de como usar PChar:

Internamente(manipulação com PChar por questões de performance)
function Bah(const S: String; Ch: Char): Integer;
var
  P, Q: PChar;
begin
  P := Pointer(S);
  Q := P + Length(S);
  Result := 0;
  while P < Q do
  begin
    if P^ = Ch then Inc(Result);
    Inc(P);
  end;
end;


Externamente(conversão para PChar por necessidade)
function Bah(S: PChar; Ch: Char): Integer; external ´mydll.dll´;
...
Bah(PChar(MinhaVariavelString), ´ ´);


Espero ter podido esclarecer as diferenças. É perfeitamente possível manter seu código atual(e se estiver rodando sem problemas, deixe assim mesmo), mas há a questão da praticidade.


Responder

Gostei + 0

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

Aceitar