Problema com PChar
Ao executar esta rotina ela dá erro em System.LoadResString
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
e o compilador para na linha
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
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
Curtidas 0
Respostas
Beppe
24/07/2005
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.
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.
GOSTEI 0
José Henrique
24/07/2005
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.
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.
GOSTEI 0
Kapak
24/07/2005
Vc está mandando o ponteiro de Edit1.Text e:E:
Então tente substituir:Por:
Na chamada da função:Então substitua:
strNome := ptrPos; // Aqui vc perde a referência
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;
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;
try strRes := TrataNomeP(PChar(Edit1.Text)); Edit2.Text := StrPas(strRes); finally StrDispose(strRes); end;
GOSTEI 0
José Henrique
24/07/2005
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
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
GOSTEI 0
Beppe
24/07/2005
[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)
Externamente(conversão para PChar por necessidade)
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.
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.
GOSTEI 0