MINGW gccでコンパイルすると、std :: stringに対してオーバーロードされた新しい演算子が呼び出されない


8

このプログラム(オプションでコンパイル-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;
}

ClangまたはMSVSでコンパイルすると、次のように出力されます。

ヒープに4バイトを割り当てる

ヒープに2016バイトを割り当てる

ただし、GCC(Windows上のMSYSによって提供されるバージョン9.2.0)でコンパイルされた場合は、次の内容のみが出力されます。

ヒープに4バイトを割り当てる

GCC / libc ++での短い文字列の最適化を知っていますが、短い文字列に対して2000文字が多すぎませんか?それはSSOの問題ですか?


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
Samuel Liew

回答:


4

GCCにはないようだ(か?できません)グローバルの交換を実装operator newし、operator delete動的ライブラリは、Windows上で関与しているときに正しくが。

例えばバグレポートを参照してください7772682122および81413を

あなたの場合、std::stringコンストラクタstd::allocator<char>::allocateが標準ライブラリの動的ライブラリに配置されているように見えるため、コンストラクタoperator newが正しく置き換えられていません。


1
さらに明確にするために、この動作は、MSYS / MINGWが提供するWindowsでlibc ++をGCCで使用した場合にのみ観察されました。Ubuntu上のGCC / libstdc ++のすべてのバージョンは、ClangまたはMSVSでコンパイルされたプログラムとまったく同じように機能しました。さらに、GCCでコンパイルすると、sizeof(str)利回りとして、SSOのケースではないことは明らか32です。
Angle.Bracket

@ Angle.Bracket libc ++ではなくlibstdc ++を意味しますか?
クルミ

MINGWでlibc ++と呼ばれていると思います
Angle.Bracket

@ Angle.Bracket libc ++は通常、clang用のLLVMプロジェクトの標準ライブラリ実装を指します。mingwかどうかに関係なく、gccがそれを使用できるとは思いません。しかし、私はここで間違っているかもしれません。
ウォールナット

@ Angle.Bracket この質問の回答を使用して、libstdc ++を使用しているかlibc ++を使用しているかを確認できます。
クルミ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.