O acesso a um objeto não volátil declarado através de uma referência / ponteiro volátil confere regras voláteis aos referidos acessos?

Será longo, para contextualizá-lo e fornecer o máximo de informações possível, preciso percorrer vários links e citações - como costuma ser a única maneira de entrar no C / C ++ Standard Rabbit Hole. Se você tiver melhores citações ou outras melhorias para este post, entre em contato. Mas, para resumir de antemão,você pode culpar @zwol para mim postar isso ;-) e o objetivo é encontrar a verdade dentre duas proposições:

Os padrões C e (por importação; ver comentários) C ++ exigem que os acessos viavolatile * ouvolatile & deve se referir a um objeto originalmente declaradovolatile para tervolatile semântica?Ouestá acessando umvolatileobjeto qualificado por meio de umvolatile ponteiro / referência suficiente / suposto para fazer com que os referidos acessos se comportem como se o objeto fosse declaradovolatile?

De qualquer forma, se (como parece) a redação for um tanto ambígua em comparação com a intenção -podemos deixar isso claro nas próprias normas?

A primeira dessas interpretações mutuamente exclusivas é mais comumente realizada, e isso não é totalmente sem base. No entanto, espero mostrar que há uma quantidade significativa de "dúvida razoável" a favor do 2º - especialmente quando voltamos a algumas passagens anteriores nos documentos do Rationale and WG Papers.


Sabedoria aceita: o próprio objeto referido deve ter sido declaradovolatile

Pergunta popular de ontemA definição de "volátil" é volátil ou o GCC está tendo alguns problemas de conformidade padrão? surgiu assumindo umavolatile referência confeririavolatile comportamento nãovolatile referente - mas descobrindo que isso não aconteceu ou ocorreu em graus variados e de maneira imprevisível.

A resposta aceita inicialmente concluiu que apenas o tipo declarado de referente era importante. Este e muitos comentários pareciam concordar que princípios equivalentes estão em jogo, como sabemos bem porconst: o comportamento seria apenasvolatile (ou definido) se a referência tiver o mesmocv-qualificação como o objeto referido:

A palavra-chave nessa passagem é objeto.volatile sig_atomic_t flag; é um objeto volátil.*(volatile char *)foo é meramenteum acesso através de um valor qualificado de volátil e a norma não exige que isso tenha efeitos especiais. -zwol

Essa interpretação parece ser amplamente aceita, como visto nas respostas a essa pergunta semelhante, mas espero que não seja duplicada:Requisitos para o comportamento de apontar ponteiro para volátil para objeto não volátil Mas ainda há incerteza: logo após a resposta dizer 'não', então diz 'talvez'! Enfim ... vamos verificar o padrão para ver em que os 'não' se baseiam.


O que o Padrão diz ... ou não

C11,N1548, §6.7.3: Considerando que é claro que é UB acessar um objetodefinido com volatile ouconst digite através de um ponteiro que não compartilhe o qualificador ...

6 Se for feita uma tentativa de modificar um objeto definido com umconstqualificado pelo uso de um valor l com valores nãoconst-qualificado, o comportamento é indefinido. Se for feita uma tentativa de se referir aum objeto definido com umvolatiletipo qualificado através do uso de um valor l comvolatile-tipo qualificado, o comportamento é indefinido. (133)

... a Norma não parece mencionar explicitamente o cenário oposto, nomeadamente paravolatile. Além disso, ao resumirvolatile e operações sobre ele, agora fala sobre um objeto quetem volatiletipo qualificado:

7 Aobjeto que possuivolatiletipo qualificado pode ser modificado de maneiras desconhecidas para a implementação ou ter outros efeitos colaterais desconhecidos. Portanto, qualquer expressão referente a esse objeto deve ser avaliada estritamente de acordo com as regras da máquina abstrata, conforme descrito em 5.1.2.3. Além disso, em cada ponto da sequência, o valor armazenado pela última vez no objeto deve concordar com o prescrito pela máquina abstrata, exceto conforme modificado pelos fatores desconhecidos mencionados anteriormente. (134) O que constitui um acesso a um objeto que possuivolatiletipo qualificado é definido pela implementação.

Devemos assumir que "has" é equivalente a "foi definido com"? oupode "tem" refere-se a uma combinação de objeto e qualificadores de referência?

Um comentarista resumiu bem a questão com este tipo de redação:

Den1548 §6.7.3 ¶6 a norma usa a frase "objeto definido com um tipo qualificado para uso volátil" para distingui-lo de "lvalue com tipo qualificado para uso volátil". É lamentável que esse "objeto definido com a distinção" versus "lvalue" não continue, e o padrão use "objeto que possui um tipo qualificado de volátil" e diz que "o que constitui acesso a um objeto que tem um tipo qualificado de volátil é definido pela implementação "(que poderia ter dito" lvalue "ou" objeto definido com "para maior clareza). Ah bem. -Dietrich Epp

O parágrafo 4 da mesma seção parece ser menos frequentemente citado, mas pode ser relevante, como veremos na próxima seção.


Dúvida razoável: É / foi umvolatile ponteiro / referência destinado a conferirvolatile semântica em sua desreferência?

A resposta acima mencionada tem um comentário em que o autor cita uma declaração anterior do Comitê que põe em dúvida a idéia 'a referência deve corresponder ao referente':

Curiosamente, há uma frase lá [C99 Justificativa paravolatile] implica que o comitêsignificava para*(volatile T*)x para forçar esse acesso ax ser tratado como volátil; mas a redação real do padrão não alcança isso. - zwol

Podemos encontrar um pouco mais de informações sobre esse trecho da justificativa, a partir do segundo tópico mencionado acima:Requisitos para o comportamento de apontar ponteiro para volátil para objeto não volátil

Por outro lado,esta postagem citações do 6.7.3 do Rationale for International Standard - Linguagens de programação - C:

Uma conversão de um valor para um tipo qualificado não tem efeito; a qualificação (volátil, digamos) não pode afetar o acesso, uma vez que ocorreu antes do caso.Se for necessário acessar um objeto não volátil usando semântica volátil, a técnica é converter o endereço do objeto no tipo apropriado de ponteiro para qualificado e desreferenciar esse ponteiro.

philipxy

E deesse segmento de bytes, nos referimos a C99 s6.7.3 p3 - também conhecido como p11 de C11 - e a esta análise:

O parágrafo em questão é um pouco antes da seção 6.7.3.1 no documento de justificativa. Se você também precisar citar o próprio documento padrão, cite6.7.3 p3:

As propriedades associadas aos tipos qualificados são significativas apenas para expressões que são lvalues.

A expressão(volatile WHATEVER) non_volatile_object_identifier énão um valor l, portanto o qualificador 'volátil' não tem sentido.

Por outro lado, a expressão* (volatile WHATEVER *) & non_volatile_object_identifier é um valor (pode ser colocado no lado esquerdo de uma declaração de atribuição), portanto, a propriedade do qualificador 'volátil' tem o significado pretendido neste caso.

Tim Rentsch

Existe ummuito demonstração específica de apoio a esta ideia, com especial atenção à 1ª questão ligada, emWG PaperN1381. Isto introduziu o anexomemset_s() para fazer o que o OP queria - garantir um preenchimento não-exagerado da memória. Ao discutir possíveis implementações, parece apoiar a idéia - omitindo declarar qualquer requisito - de que usar umvolatile apontador para alterar umvolatile objetodevemos gerar código com base noqualificador do ponteiro, independentemente do objeto referido ...

Solução 'secure-memset' independente de plataforma:
void *secure_memset(void *v, int c , size_t n) {
    volatile unsigned char *p = v;
    while (n--) *p++ = c;
    return v;
}

Essa abordagem impedirá que a limpeza da memória seja otimizada edeve funcionar em qualquer plataforma compatível com os padrões.

... e que os compiladores que não estão fazendo isso estão informados ...

Houve um aviso recente de quealguns compiladores violam o padrão nem sempre respeitando ovolatile qualificador.


Quem está certo?

Isso foi cansativo. Certamente há muito espaço para interpretação aqui, dependendo de quais documentos você leu versus quais não, e como você escolhe interpretar muitas palavras que não são específicas o suficiente. Parece claro que algo está errado:

a justificativa e N1381 têm palavras erradas ou aleatoriamente, oueles foram especificamente invalidados retroativamente ... ouo Padrão é redigido de maneira errada ou aleatória.

Espero que possamos fazer melhor do que toda a ambiguidade e especulação que parece ter cercado isso no passado - e obter uma declaração mais conclusiva registrada. Para esse fim, quaisquer outras fontes e pensamentos de especialistas serão muito bem-vindos.

questionAnswers(4)

yourAnswerToTheQuestion