Ao compilar com o MINGW gcc, o novo operador sobrecarregado não é chamado para std :: string

8

Este programa (compilado com a opção -std=c++17)

#include <stdio.h>
#include <string>
void* operator new(std::size_t nrOfBytes) {
    printf("allocate %zd bytes on heap\n", nrOfBytes);
    void* p = malloc(nrOfBytes);
    if (p) {
        return p;
    } else {
       throw std::bad_alloc{};
    }
}
int main() {
    // new operator is called when compiled with Clang or MSVS or GCC 
    int* i = new int;
    delete i;
    // new operator is not called when compiled with GCC
    // but is called with Clang and MSVS 
    std::string str(2000, 'x');
    return 0;
}

quando compilado com Clang ou MSVS, imprime:

alocar 4 bytes na pilha

alocar 2016 bytes na pilha

No entanto, quando compilado com o GCC (versão 9.2.0 fornecida pelo MSYS no Windows), ele apenas imprime:

alocar 4 bytes na pilha

Estou ciente da otimização de cadeia curta no GCC / libc ++, mas 2000 caracteres não são muitos para uma cadeia curta? É uma questão de SSO?

Suporte angular
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Samuel Liew

Respostas:

4

Parece que o GCC não implementa (ou não pode?) Implementar a substituição do global operator newe operator deletecorretamente quando bibliotecas dinâmicas estão envolvidas no Windows.

Veja relatórios de bugs, por exemplo, 77726 , 82122 e 81413 .

No std::stringconstrutor do seu caso e / ou std::allocator<char>::allocateparece estar localizado na biblioteca dinâmica da biblioteca padrão, para que operator newela não seja substituída corretamente.

noz
fonte
1
Para esclarecer: esse comportamento só foi observado ao usar o GCC com libc ++ no Windows fornecido pelo MSYS / MINGW. Todas as versões do GCC / libstdc ++ no Ubuntu eu era capaz de testar funcionavam exatamente como os programas compilados com Clang ou MSVS. Além disso, claramente não é um caso de SSO quando compilado com o GCC, conforme o sizeof(str)rendimento 32.
Angle.Bracket 14/01
@ Angle.Bracket Você quer dizer libstdc ++ em vez de libc ++?
noz
Eu acho que é chamado libc ++ em MINGW
Angle.Bracket
@ Angle.Bracket libc ++ geralmente se refere à implementação da biblioteca padrão do projeto LLVM para clang. Eu não acho que o gcc é capaz de usá-lo, misturado ou não. Mas posso estar errado aqui.
walnut
@ Angle.Bracket Acho que você pode verificar se está usando libstdc ++ ou libc ++ usando as respostas nesta pergunta .
walnut