Pergunta

Preciso converter ponteiros para long (sendMessage ()) e quero verificar com segurança se a variável está correta no outro lado. Então, eu estava pensando em fazer dinâmico_cast, mas isso não funcionará em classes que não são virtuais. Então pensei em fazer o TypeID, mas isso funcionará até que eu passe um VAR derivado como base.

Existe alguma maneira de verificar se o ponteiro é o que estou esperando durante o tempo de execução? Existe uma maneira de usar o TypeID para ver se um ponteiro é um tipo derivado de uma base específica?

Foi útil?

Solução

Se tudo que você tem é um long, então não há muito que você possa fazer. Não existe uma maneira geral de determinar se um número arbitrário representa um endereço de memória válido. E mesmo que você saiba que é um endereço de memória válido, não há como determinar o tipo de coisa que o ponteiro aponta. Se você não pode ter certeza do tipo real da coisa antes de seu endereço ser lançado para long, então você não pode ter certeza de que será seguro lançar o long Para qualquer tipo que você planeja lançá -lo.

Você só precisará confiar que o remetente da mensagem enviou um valor válido. O melhor que você pode fazer é tomar algumas precauções para reduzir as consequências para o seu próprio programa quando receber um valor falso.

Outras dicas

Sua referência a SendMessage() faz com que eu pareça como o MS Windows é sua plataforma e depois o Regras para o uso de ponteiros (Windows) é a leitura recomendada. Detalha o PtrToLong e PtrToUlong Funções e outras coisas que a Microsoft fornece para você em situações como essa.

Você não pode usar o tipoID. Isso resultará em uma violação de acesso se você receber lixo em vez de um ponteiro válido, para que seu cheque seja absurdo.

O que você deve fazer é envolver sua sendmessage e o código que processa a mensagem em uma única interface de tipo. Dessa forma, você não poderá passar coisas inesperadas para a SendMessage e não precisará de nenhum cheque no lado recebido.

O sistema de tipo C ++ funciona no horário de compilação. Depois de lançar um ponteiro por muito tempo, você perde todas as informações do tipo. Um longo é tanta bits na memória; Não há como identificar que estava apontando para um objeto.

Ptlib ( http://sourceforge.net/projects/opalvoip/ ) usa uma macro pclassinfo para definir as relações entre as classes. Isso fornece funções como IsDescendente e GetClass.

Você provavelmente poderia implementar algo semelhante.

Dynamic_cast funciona verificando a assinatura da tabela de métodos virtuais. Se você não possui métodos virtuais, não tem VMT, portanto, como diz o Dynamic_cast, não funcionará. No entanto, se você não tiver VMT, não tem absolutamente nenhum conhecimento sobre o objeto que está sendo apontado.

Sua melhor aposta é exigir que os ponteiros sejam para aulas com pelo menos um método virtual, mesmo que seja um manequim. O elenco dinâmico funcionará então.

Ainda não entendo o que é sua pergunta.

  • Se for, se você pode ou não ter certeza de que o lançamento para um longo e as costas produzirá o mesmo valor, veja Verificando com segurança o tipo de variável
    Dadas as "regras para usar ponteiros" no local do MS, o outro respondente vinculado, o tipo certo a ser lançado é UINT_PTR. Então você faz UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr); lançar -se para um tipo integral e fazer o inverso para lançá -lo de volta ao ponteiro novamente. O padrão C ++ garante que o valor original seja restaurado. (Veja o link que dei acima para minha explicação disso). A propósito, esse site da Microsoft também diz que o WPARAM e o LPARAM mudam seu tamanho, dependendo da plataforma. Então você poderia usar essa variável v e SendMessage isto.
  • Se é como você pode verificar por outro lado se o ponteiro (convertido em algum tipo de ponteiro) aponta para algum objeto, a resposta é você não pode. Como você aparentemente não tem certeza de qual tipo de ponteiro foi usado para enviá -lo, você não pode verificar no lado receptor o que o tipo dinâmico que o ponteiro aponta é. Se você souber o tipo que o ponteiro tinha no lado do remetente, seu cheque não seria necessário em primeiro lugar.

No Windows, o MFC fornece um método para verificar se um determinado ponteiro está apontando para um local de memória válido (isso é feito prendendo o Segfault). Não me lembro do nome da função, mas está lá. Ainda assim, ele não garante que o conteúdo da memória apontado seja válido. Ainda pode ter VMT inválido e travar seu código. Claro, você pode prender o segfault (Veja MS Base de Conhecimento)

Quanto à verificação, se algo pertence a um tipo, você deve ter uma classe base para começar. Se você fizer o destruidor da classe base "virtual", todas as classes derivadas terão VMTs.

Se você precisar evitar o VMT a todo custo, precisa ter algum tipo de descrinação que informe com o que você está lidando, como o tipo de evento nos eventos do MS Windows.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top