Com o lançamento do DataFlex 2021, introduzimos a capacidade de compilar e executar sua aplicação como um executável de 64 bits. Embora, preparar seu código para compilação de 64 bits não seja, geralmente tão difícil quanto você possa temer, e haja uma boa orientação no nosso DataFlex Learning Center, alguns desenvolvedores podem se deparar com o curioso caso de structure padding. Confesso que a primeira vez que me deparei com o assunto, fiquei um pouco surpreso.
O problema é que structs expostas às funções do Windows ou dependências personalizadas podem precisar de pequenas alterações para ainda funcionarem corretamente. Mas, como você reconhece que tais mudanças são necessárias? Como isso nem sempre é óbvio para todos os desenvolvedores, criamos uma pequena ferramenta para ajudá-lo.
Structure padding consiste em alinhar structs ao seu maior membro adicionando espaços extras dentro do struct. Muitas linguagens e sistemas fazem isso, como o Windows, e o compilador C/C++ no Visual Studio que fazem isso por padrão. Este último pode ser desligado, o que não é feito com frequência. O DataFlex não faz structure padding (por motivos históricos), com o resultado de que uma struct na memória DataFlex pode não corresponder exatamente à struct que o Windows ou o componente externo espera. Isso pode levar a um erro de tempo de execução ou outro comportamento inesperado ao chamar a DLL externa ou a API do Windows. A propósito, esse problema não se aplica a objetos COM.
Como exemplo, observe a figura abaixo. Isso exibe o uso de memória da seguinte struct definida em C/C++:
O maior membro na struct é de 4 bytes, o que significa que os membros da struct serão alinhados em partes de 4 bytes e nenhum membro da struct excederá qualquer parte. O resultado é que a área indicada em rosa está vazia. Assim, o compilador C/C++ adiciona espaço vazio na memória para alinhar a porcentagem no início de um bloco de dados de 4 bytes. Se você solicitasse o tamanho da struct em C/C++, obteria a resposta 16, não 14.
O DataFlex não adiciona o espaço vazio, então no DataFlex a struct seria de 14 bytes. E se você passar para a função externa C/C++, você obterá uma incompatibilidade. Essa função espera que a porcentagem comece no byte 13, mas começa no byte 11.
O exemplo acima mostra um caso de padding que já se aplica à compilação de 32 bits. No entanto, raramente vi um caso em que o structure padding seja relevante em 32 bits, e este não é um exemplo da vida real. Mas em 64 bits é muito mais relevante! Dê uma olhada no seguinte exemplo da vida real:
Esta é a definição do DataFlex de uma struct do Windows que pode ser passada para as funções do Windows. Muitos desenvolvedores não percebem imediatamente que temos um problema aqui em 64 bits, mas não em 32 bits. Por quê? Primeiro, tWinPoint é uma struct interna e na memória se qualifica como um ponteiro. Em 32 bits todos os membros são 4 bytes. Mas em 64 bits, tanto o ponteiro quanto o handle são 8 bytes (64 bits), enquanto o DWord ainda tem 4 bytes. Isso leva ao seguinte alinhamento no Windows:
Portanto, na struct do Windows, há padding extra após o DWord. Para explicar isso, devemos fazer uma alteração na struct DataFlex, de modo que na memória seja igual ao que a função do Windows espera. Podemos fazer isso adicionando manualmente um espaço reservado no DataFlex, assim:
Somente em 64 bits, outro membro de 4 bytes é adicionado após o DWord, o que é feito usando a instrução #IFDEF. O membro extra não precisa receber um valor e seu nome é bastante irrelevante.
Recebemos solicitações para criar uma ferramenta para ajudar os desenvolvedores a adicionar o padding certo nos lugares certos. Então, nós fizemos!
No lado esquerdo você pode inserir uma ou mais structs, ou até mesmo colar o conteúdo de um arquivo fonte completo. Depois de clicar no botão Analyze, ele insere itens de padding onde for necessário (lado direito).
O download é uma workspace 20.0 que você pode compilar e executar. Isso também pode ser usado no DataFlex 2022 (20.1).