ActiveDelphi - Índice do Fórum ActiveDelphi
.: O site do programador Delphi! :.
 
 FAQFAQ   PesquisarPesquisar   MembrosMembros   GruposGrupos   RegistrarRegistrar 
 PerfilPerfil   Entrar e ver Mensagens ParticularesEntrar e ver Mensagens Particulares   EntrarEntrar 

Recebendo Acecss Violation em array. [Resolvido]

 
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi
Exibir mensagem anterior :: Exibir próxima mensagem  
Autor Mensagem
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Seg Set 09, 2013 10:17 pm    Assunto: Recebendo Acecss Violation em array. [Resolvido] Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
CesarRocha
Mestre
Mestre


Registrado: Segunda-Feira, 30 de Mai de 2011
Mensagens: 794
Localização: São Paulo - SP

MensagemEnviada: Ter Set 10, 2013 10:42 am    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Ter Set 10, 2013 1:29 pm    Assunto: Responder com Citação

Boa tarde,

Concordo com o Cesar... confira um exemplo de código com array dynâmico no tópico abaixo:
http://www.activedelphi.com.br/forum/viewtopic.php?t=66112&start=0&postdays=0&postorder=asc&highlight=&sid=cc765e48f237c7ba6e1a67da416e5b6c

Espero que ajude.


Editado pela última vez por imex em Sex Set 29, 2023 12:03 pm, num total de 1 vez
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Ter Set 10, 2013 10:44 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Qua Set 11, 2013 3:42 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Sex Set 13, 2013 6:04 am    Assunto: Responder com Citação

Obrigado a todos pela ajuda, a maneira que o Imex postou resolveu o problema.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Sex Set 13, 2013 6:34 am    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Sex Set 13, 2013 12:07 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Sex Set 13, 2013 11:18 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Dom Set 15, 2013 10:05 am    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Dom Set 15, 2013 2:57 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Seg Set 16, 2013 11:03 pm    Assunto: Responder com Citação

UP
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
CesarRocha
Mestre
Mestre


Registrado: Segunda-Feira, 30 de Mai de 2011
Mensagens: 794
Localização: São Paulo - SP

MensagemEnviada: Ter Set 17, 2013 9:57 am    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Ter Set 17, 2013 1:34 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
marcosbaixista
Profissional
Profissional


Registrado: Quinta-Feira, 18 de Março de 2010
Mensagens: 594
Localização: Maringá/PR

MensagemEnviada: Ter Set 24, 2013 1:53 pm    Assunto: Responder com Citação

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
Ver o perfil de Usuários Enviar Mensagem Particular
Mostrar os tópicos anteriores:   
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi Todos os horários são GMT - 3 Horas
Página 1 de 1

 
Ir para:  
Enviar Mensagens Novas: Proibido.
Responder Tópicos Proibido
Editar Mensagens: Proibido.
Excluir Mensagens: Proibido.
Votar em Enquetes: Proibido.


Powered by phpBB © 2001, 2005 phpBB Group
Traduzido por: Suporte phpBB