Por que essa violação de acesso ocorrerá com os sinalizadores / Og e / GL, com passagem por referência?

9

Quando (e somente quando) eu compilo meu programa com o /Og e /GL flag usando o compilador do Windows Server 2003 DDK C ++ bem no WDK 7.1, bem como no Visual Studio 2010!), recebo uma violação de acesso quando executo o seguinte:

#include <algorithm>
#include <vector>

template<typename T> bool less(T a, T b) { return a < b; }

int main()
{
    std::vector<int> s;

    for (int i = 0; i < 13; i++)
        s.push_back(i);

    std::stable_sort(s.begin(), s.end(), &less<const int&>);
}

A violação de acesso desaparece quando eu altero a última linha para

    std::stable_sort(s.begin(), s.end(), &less<int>);

- em outras palavras, desaparece quando eu deixo meu item ser copiado em vez de meramente referenciado .

(Eu não tenho multithreading de qualquer tipo acontecendo em absoluto.)

Por que algo assim aconteceria? Estou invocando algum comportamento indefinido passando por const & ?

  • Sinalizadores do compilador:

    /Og /GL /MD /EHsc
    
  • Sinalizadores do vinculador: (nenhum)

  • INCLUIR variável ambiental:

    C:\WinDDK90.1830\inc\crt
    
  • Variável ambiental LIB:

    C:\WinDDK90.1830\lib\crt\I386;C:\WinDDK90.1830\lib\wxp\I386
    
  • Sistema operacional: Windows 7 x64

  • Plataforma: a compilação de 32 bits fornece erro (a execução de 64 bits é correta)

Editar:

Eu apenas tentei com o DDK do Windows XP (que é C:\WinDDK00 ) e recebi:

error LNK2001: unresolved external symbol
    "bool __cdecl less(int const &,int const &)" (?less@@YA_NABH0@Z)

mas quando eu mudei de um template para uma função regular , ele magicamente funcionou com ambos compiladores!

Estou suspeitando que isso significa que eu encontrei um bug que acontece ao obter o endereço de uma função de modelo, usando os compiladores DDK. Alguma idéia se esse pode ser o caso, ou se é um caso diferente que eu não conheço?

    
por Mehrdad 30.08.2011 в 03:33
fonte

2 respostas

5

Eu tentei isso com uma instalação do Windows Server 2003 DDK SP1 (o DDK não-SP1 não está disponível no momento). Isso usa o cl.exe versão 13.10.4035 para 80x86. Parece ter o mesmo problema que você encontrou.

Se você percorrer o código em um depurador (que fica um pouco mais fácil seguindo o arquivo .cod gerado usando a opção /FAsc ), verá que a função less<int const &>() espera ser chamada com os ponteiros para os valores int passaram em eax e edx . No entanto, a função que chama less<int const&>() (denominada _Insertion_sort_1<>() ) a chama passando os ponteiros na pilha.

Se você transformar a função less em uma função sem modelo, espera que os parâmetros sejam passados na pilha, para que todos fiquem felizes.

De um pouco mais de interesse é o que acontece quando você altera less<const int&> para less<int> . Não há nenhum acidente, mas nada é classificado também (é claro, você precisaria mudar o seu programa para começar com um vetor não classificado para realmente ver esse efeito). Isso porque quando você muda para less<int> , a função less não mais faz referência a nenhum ponteiro - espera que os valores int reais sejam passados nos registradores ( ecx e edx nesse caso). Mas nenhuma referência de ponteiro significa nenhum acidente. No entanto, o chamador, _Insertion_sort_1 , ainda passa os argumentos na pilha, portanto, a comparação sendo executada por less<int> não tem nada a ver com os valores no vetor.

Então é isso que está acontecendo, mas eu realmente não sei qual é a causa raiz - como outros já mencionaram, parece um erro de compilador relacionado às otimizações.

Como o bug aparentemente foi corrigido, obviamente não há sentido em reportá-lo (o compilador nessa versão do DDK corresponde a algo próximo ao VS 2003 / VC 7.1).

A propósito - eu não consegui obter o seu exemplo para compilar completamente limpo - para fazê-lo construir, eu tive que incluir o bufferoverflowu.lib para obter o material de verificação da pilha para linkar, e mesmo assim o vinculador reclamou sobre "várias seções '.rdata' encontradas com diferentes atributos". Eu pareço lembrar que ser um aviso que era seguro ignorar, mas eu realmente não me lembro. Eu não acho que qualquer um destes tenha algo a ver com o bug.

    
por Michael Burr 30.08.2011 / 08:07
fonte
0

Se você não conseguir em compiladores mais novos, é mais provável que seja um bug.

Você tem uma pequena reprodução independente?

    
por Ben Voigt 30.08.2011 / 03:45
fonte