Estou ciente de que múltiplas cargas não voláteis podem ser colapsadas em uma única carga pelo compilador. Isso significa que funções de mapeamento de memória podem criar comportamento indefinido?
por exemplo:
int k = *p;
unmapFile(fm, fileHandle1);//the unmapped memory includes the address pointed to by p
//p is no longer valid, pointing to a virtual address that is unmapped
mapFile(fm, fileHanlde2);//p now points to an address somewhere in a different file
int j = *p;
//use k and j here
as duas desreferências de p podem ser reunidas em uma, fazendo com que o código se comporte de forma imprevisível?
como um aparte, eu sei que funções de mapeamento de arquivo não permitem que você especifique o endereço inicial do mapa (pelo menos em posix e windows), mas essa foi a hipótese mais simples que eu consegui pensar. De fato, há casos de uso para esse paradigma.
O C em si não define nenhuma dessas funções ou fala sobre como elas poderiam ou deveriam funcionar se definidas. Portanto, no que diz respeito à especificação da linguagem C, tudo e qualquer coisa associada a funções de mapeamento de memória tem comportamento indefinido. Não há outra resposta no nível de generalidade da questão. Como @AtsushiYokoyama observa , há questões práticas que podem dissuadir o compilador de combinar as duas leituras de
*p
, mas isso não deve ser tomado como garantia de que qualquer compilador dado de fato não as combinará.Em um ambiente de programação e execução que disponibiliza funções de mapeamento de memória, a maioria dos detalhes relacionados ao seu comportamento, na medida em que são definidos, são específicos da implementação. Considerando um ambiente POSIX que suporta mapeamentos de arquivo e as funções POSIX
mmap()
emunmap()
como exemplo, POSIX diz:E diz:
e
É responsabilidade do compilador garantir que quaisquer otimizações que ele execute preservem a semântica do programa conforme definido pela combinação de todas as especificações relevantes. Não vejo nenhuma maneira de um compilador para um ambiente POSIX onde your
unmapFile()
corresponde amunmap()
e yourmapFile()
correspondemmap()
a justificar a combinação das duas leituras de*p
. Isso não significa que nenhum compilador faria isso, mas significa que um compilador que fizesse isso correria o risco de produzir um comportamento de programa que não estivesse em conformidade com POSIX. Para este caso, então, eu reforçaria minha observação acima para: há questões práticas que devem dissuadir o compilador de combinar as duas leituras de*p
.Quando o compilador realiza otimização neste tipo de código, se ele não conhece a implementação de
unmapFile()
oumapFile()
(por exemplo, se são funções externas), então, em geral , as duas referências por meio de ponteiro nãop
serão colapsadas em uma. Isso ocorre porque o compilador não pode garantir que essas funções não tenham efeitos colaterais que afetem a referência a .p
Por outro lado, se o compilador conhece a implementação de
unmapFile()
emapFile()
(por exemplo, se sãoinline static
funções) e está confiante de que essas funções não afetam a referência ap
, então ele pode colapsar as referências por meio dep
.Claro, como você ressaltou, se forem
volatile
, a história seria diferente.Espero que isso ajude!