| Exibir mensagem anterior :: Exibir próxima mensagem |
| Autor |
Mensagem |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Seg Set 09, 2013 10:17 pm Assunto: Recebendo Acecss Violation em array. [Resolvido] |
|
|
Olá pessoal.
Estou enfrentando um problema de Access Violation em uma função que até dias atrás estava funcionando normalmente.
No início da Unit estou declarando esta variável:
| Código: |
{$R *.res}
type
TPermissao = array of string;
|
O erro ocorre quando passo por uma variável do tipo array, abaixo o código:
| Código: |
Function AcessoTela(Tela: Integer; Usuario: Integer): TPermissao; stdcall;
var
Botoes: TPermissao;
Campo: String;
I: Integer;
begin
IniciaDLL;
try
try
DadosFuncao.QryAuxiliar.Close;
DadosFuncao.QryAuxiliar.SQL.Clear;
DadosFuncao.QryAuxiliar.SQL.Add('SELECT * FROM FUNCAOUSU WHERE CODTELA = ' + IntToStr(Tela) + ' AND CODUSUARIO = ' + IntToStr(Usuario));
DadosFuncao.QryAuxiliar.Open;
for I:= 0 to 3 do begin
case I of
0:Campo:= 'CONSULTAR';
1:Campo:= 'INCLUIR';
2:Campo:= 'ALTERAR';
3:Campo:= 'EXCLUIR';
end;
if DadosFuncao.QryAuxiliar.FieldByName(Campo).AsString = '' then
Botoes[I] := 'n' //o Access Violation acontece aqui.
else
Botoes[I] := DadosFuncao.QryAuxiliar.FieldByName(Campo).AsString; //o Access Violation acontece aqui.
end;
DadosFuncao.QryAuxiliar.Close;
Result:= Botoes;
except
on erro: Exception do begin
if not TVerificaException.TrataExcception(erro) then begin
Assert(False, '');
TVerificaException.SalvarLog(erro);
raise;
end;
end;
end;
finally
FinalizaDLL;
end;
end;
|
Alguém tem alguma idéia porque isso está acontecendo?
Estou usando delphi XE3 e Firebird.
Desde já agradeço a ajuda de todos.[/code]
Editado pela última vez por marcosbaixista em Ter Set 24, 2013 1:54 pm, num total de 3 vezes |
|
| Voltar ao Topo |
|
 |
CesarRocha Mestre

Registrado: Segunda-Feira, 30 de Mai de 2011 Mensagens: 794 Localização: São Paulo - SP
|
Enviada: Ter Set 10, 2013 10:42 am Assunto: |
|
|
Esse código funcionava antes? Pois não faz sentido, você está tentando acessar um índice do array dinâmico, mas em nenhum lugar o tamanho está sendo definido... com isso você pode acessar uma posição inexistente, ocasionando um "Access Violation".
~bye |
|
| Voltar ao Topo |
|
 |
imex Moderador

Registrado: Sexta-Feira, 7 de Janeiro de 2011 Mensagens: 11666
|
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Ter Set 10, 2013 10:44 pm Assunto: |
|
|
Olá Cesar e Imei.
Não entendi essa do tamanho.
Vocês falam determinar quantas posições o array vai possuir, é isso?
Tipo teria que declarar no tipo de variável assim:
| Código: |
TPermissao: array[1..4] string;
|
Seria mais ou menos isso? |
|
| Voltar ao Topo |
|
 |
imex Moderador

Registrado: Sexta-Feira, 7 de Janeiro de 2011 Mensagens: 11666
|
Enviada: Qua Set 11, 2013 3:42 pm Assunto: |
|
|
Se você declarar assim
| Código: | | TPermissao: array[1..4] string; |
terá um array estático com 4 elementos.
Se você declarar assim
| Código: | | TPermissao = array of string; |
terá um array dinâmico, sendo que para definir a quantidade de elementos desse array e alocar memória para eles deve ser executada a procedure SetLength. Exemplo para 4 elementos:
| Código: | | SetLength(Botoes, 4); |
O detalhe nesse caso é que o índice do primeiro elemento é 0, e o do último é 3.
Ou seja, a quantidade de elementos de um array dinâmico é definida durante a execução, sendo possível também aumentar e diminuir a quantidade mesmo depois que o array é "carregado" com valores.
Acho que seria interessante adicionar o código que postei naquele outro tópico dentro de um botão, e executa-lo com debug para analisar o seu funcionamento.
Espero que ajude. |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Sex Set 13, 2013 6:04 am Assunto: |
|
|
| Obrigado a todos pela ajuda, a maneira que o Imex postou resolveu o problema. |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Sex Set 13, 2013 6:34 am Assunto: |
|
|
Olá pessoal.
Inicialmente o problema foi resolvido, mais agora apareceu novamente o Access Violation na query que executo dentro desta função.
Se rodo a rotina a primeira vez, ela funciona normalmente, se rodar na segunda vez ele da o erro. Está acontecendo nesta linha de código:
| Código: |
SetLength(Botoes, 4);
DadosFuncao.QryAuxiliar.Close;
DadosFuncao.QryAuxiliar.SQL.Clear;
DadosFuncao.QryAuxiliar.SQL.Add('SELECT * FROM FUNCAOUSU WHERE CODTELA = ' + IntToStr(Tela) + ' AND CODUSUARIO = ' + IntToStr(Usuario)); // O erro acontece quando passa por aqui pela segunda vez.
DadosFuncao.QryAuxiliar.Open;
|
Ele gera um Access Violation quando passo nesta linha indicada no código acima.
Alguém sabe porque isso ta acontecendo?
Outra dúvida tbm.
Como faço pra liberar da memória esse array dinamico? Desta maneira estaria correto?
| Código: |
Finalize(Botoes);
|
Obrigado pela colaboração de todos. |
|
| Voltar ao Topo |
|
 |
imex Moderador

Registrado: Sexta-Feira, 7 de Janeiro de 2011 Mensagens: 11666
|
Enviada: Sex Set 13, 2013 12:07 pm Assunto: |
|
|
Sobre o Access Violation, estou achando estranho que ocorra nessa linha que você indicou, já que a query também é acessada nas linhas anteriores, e as outras variáveis acessadas nessa linha são do tipo inteiro.
Sobre a liberação do array dinâmico, ela é feita automaticamente quando não existem mais referências para ele, mas você pode utilizar o Finalize ou atribuir nil para liberar manualmente.
Espero que ajude. |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Sex Set 13, 2013 11:18 pm Assunto: |
|
|
Olá Imex, obrigado pelas respostas.
Bom, esse código está dentro de uma DLL, e chamo ele no meu executável e também por outras DLL´s. Será que não tem nada a ver com a questão de estar passando inteiros? Tive uma outra situação parecida a um tempo atrás e o problema era que eu passando string´s para a DLL, bastou mudar para PChar que o problema foi resolvido.
Que tipo de dados eu usaria no lugar de integer?
O engraçado é que só da erro quando chamo essa rotina pela segunda vez, tanto pela aplicação quanto pelas DLL´s. |
|
| Voltar ao Topo |
|
 |
imex Moderador

Registrado: Sexta-Feira, 7 de Janeiro de 2011 Mensagens: 11666
|
Enviada: Dom Set 15, 2013 10:05 am Assunto: |
|
|
Não tenho experiência com dll, mas experimente alterar o código para não utilizar os parâmetros para ver o que acontece. Ex:
| Código: | | DadosFuncao.QryAuxiliar.SQL.Add('SELECT * FROM FUNCAOUSU WHERE CODTELA = 1 AND CODUSUARIO = 2'); |
Se o erro persistir, experimente também remover os parâmetros da função/procedure para ver se faz alguma diferença.
E caso você esteja utilizando o Finalize ou atribuindo nil, experimente também comentar esse código.
Espero que ajude. |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Dom Set 15, 2013 2:57 pm Assunto: |
|
|
Olá Imex.
Tentei fazer a sua sugestão mais o problema persiste. Já to ficando louco com isso, meus cabelos já devem estar ficando brancos. kkkkkkkkk
Bom, pelo que estou analisando aqui, o problema está nos componentes de conexão, mesmo porque quando abro a tela pela segunda vez, ele retorna Access Violation nas Unit´s do componente, agora como arrumar isso só Deus sabe.
Estou utilizando Firebird e FireDAC para conexão com o banco.
Vou postar os códigos que estão na DLL, quem sabe você ou alguém aqui possa ver o que estou errando ok.
Vamos lá.
Função que chamo quando solicito abrir uma tela no sistema.
| Código: |
Function AcessoTela(Tela: Integer; Usuario: Integer): TPermissao; stdcall;
var
Botoes: TPermissao;
Campo: String;
I: Integer;
begin
IniciaDLL;
try
try
SetLength(Botoes, 4);
DadosFuncao.QryAuxiliar.Close;
DadosFuncao.QryAuxiliar.SQL.Clear;
DadosFuncao.QryAuxiliar.SQL.Add('SELECT * FROM FUNCAOUSU WHERE CODTELA = ' + IntToStr(Tela) + ' AND CODUSUARIO = ' + IntToStr(Usuario));
DadosFuncao.QryAuxiliar.Open;
for I:= 0 to 3 do begin
case I of
0:Campo:= 'CONSULTAR';
1:Campo:= 'INCLUIR';
2:Campo:= 'ALTERAR';
3:Campo:= 'EXCLUIR';
end;
if DadosFuncao.QryAuxiliar.FieldByName(Campo).AsString = '' then
Botoes[I] := 'n'
else
Botoes[I] := DadosFuncao.QryAuxiliar.FieldByName(Campo).AsString;
end;
DadosFuncao.QryAuxiliar.Close;
Result:= Botoes;
except
on erro: Exception do begin
if not TVerificaException.TrataExcception(erro) then begin
Assert(False, '');
TVerificaException.SalvarLog(erro);
raise;
end;
end;
end;
finally
Finalize(Botoes);
FinalizaDLL;
end;
end;
|
Procedures que iniciam o DataModule que está dentro da DLL.
| Código: |
procedure IniciaDLL; stdcall;
begin
if not Assigned(DadosFuncao) then begin
DadosFuncao:= TDadosFuncao.Create(nil);
end;
end;
procedure FinalizaDLL; stdcall;
begin
FreeAndNil(DadosFuncao);
end;
|
Procedure que está no OnCreate do DataModule.
| Código: |
procedure TDadosFuncao.DataModuleCreate(Sender: TObject);
var
Arquivo, Tag, Funcao, Biblioteca, Localbanco, Teste: String;
begin
if FileExists(ExtractFilePath(ParamStr(0)) + 'Config.ini') then begin
try
Arquivo:= ExtractFilePath(ParamStr(0)) + 'Config.ini';
Tag:= 'BancoDados';
Funcao:= 'Caminho';
Biblioteca:= 'Library';
Localbanco:= LerINI(Arquivo, Tag, Funcao);
ADPhysIBDriverLink1.VendorLib:= LerINI(Arquivo, Tag, Biblioteca);
with ADConexao do begin
Connected:= False;
Params.Add('DRIVERID=IB');
Params.Add('Database=' + Localbanco);
Params.Add('User_Name=sysdba');
Params.Add('Password=masterkey');
Connected:= True;
end;
except
on erro: Exception do begin
if not TVerificaException.TrataExcception(erro) then begin
Assert(False, '');
TVerificaException.SalvarLog(erro);
raise;
end;
end;
end;
end
else begin
ShowMessage('Caro Usuário:' + #13#10 +
'Parametros de Conexão com o Banco não foram encontrados!' + #13#10 +
'O sistema será finalizado' + #13#10 +
'Por Favor, entre em contato com o Suporte Técnico.');
end;
end;
|
Lembrando que todos estes códigos estão dentro de uma única DLL, inclusive o DataModule.
Quando vou abrir uma tela dentro do sistema, eu sempre solicito essa DLL para verificar o acesso do usuário, na primeira solicitação ela funciona perfeitamente, mais quando tento solicitar novamente, sendo por qualquer tela do sistema ela retorna o Access Violation, quando finalizo a execução para mostrar onde ocorreu o erro, ele me leva a essa Unit abaixo que faz parte do componente.
Nome da Unit: uADDatSManager, abaixo o código desta unit onde ele para:
| Código: |
function TADDatSNamedObject.GetDefaultName: String;
begin
Result := UpperCase(ClassName);
if (Length(Result) > 9) and (Copy(Result, 1, 7) = 'TADDATS') then
Result := Copy(ClassName, 8, Length(Result) - 7)
else
Result := ClassName;
end;
|
Ta complicado encontrar o que ta acontecendo, se alguém conseguir ajudar serei muito grato.
Desde já obrigado pela colaboração de todos. |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Seg Set 16, 2013 11:03 pm Assunto: |
|
|
| UP |
|
| Voltar ao Topo |
|
 |
CesarRocha Mestre

Registrado: Segunda-Feira, 30 de Mai de 2011 Mensagens: 794 Localização: São Paulo - SP
|
Enviada: Ter Set 17, 2013 9:57 am Assunto: |
|
|
Você já tentou similar o mesmo erro em um projeto separado? Tentei montar um projeto aqui baseado nas informações passadas, porém o erro não ocorreu.
~bye |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Ter Set 17, 2013 1:34 pm Assunto: |
|
|
Ola Cesar.
Já tentei rodar sim em um projeto separado e funciona, aqui é que ta com problemas.
Tentei trocar os componentes de acesso ao banco, usei a paleta Interbase, e da o mesmo erro, o que significa que não é o componente.
Esta função rodava normalmente até dias atrás, e do nada começou a dar problemas.
Engraçado que nesta mesma DLL tenho outras funções que acessa o mesmo componente e não ocorre erro algum.
Ta complicado encontrar o que ta acontecendo.
Mais valew pela ajuda amigo, se tiver mais idéias será muito bem vinda. |
|
| Voltar ao Topo |
|
 |
marcosbaixista Profissional

Registrado: Quinta-Feira, 18 de Março de 2010 Mensagens: 594 Localização: Maringá/PR
|
Enviada: Ter Set 24, 2013 1:53 pm Assunto: |
|
|
O problema foi resolvido declarando na uses da DLL o Sharemen.
Lendo o Help do Delphi, diz que isso gerencia a memoria da DLL. Por esse motivo eu estava tendo vários erros não só com o array como também na criação do datamodule e abertura de query´s na DLL. |
|
| Voltar ao Topo |
|
 |
|