13

私はここで不気味なことをしようとしています。GNUのg ++​​でコンパイルされたC ++プログラムを作成しようとしていますが、libstdc ++に依存していません:)しかし、最も基本的なものでさえ必要なようです。

構成可能な機能セットを備えた libstdc++ は受け入れられます。

私が使用するコマンドは

g++ -nodefaultlibs -fno-rtti -fno-exceptions -lc

libstdc++ がないと、次のようになります。

undefined reference to `operator delete(void*)'  
undefined reference to `operator new(unsigned int)'  
undefined reference to `vtable for __cxxabiv1::__class_type_info'  
undefined reference to `vtable for __cxxabiv1::__si_class_type_info'  
undefined reference to `__cxa_pure_virtual'

これらは libc にはないので、これらだけを実装する本当に軽い libstdc++ はありますか?

この方法でビルドしたいテストコードは、現在次のようになっています。

#include <stdio.h>

template <class T>
class X
{
    public:
    T a;
};

class A1
{
    public:
        virtual void f() = 0;
        virtual ~A1() {}
};

class A2 : public A1
{
    public:
        virtual void f() {};
        virtual ~A2() {}
};

class Y
{
    public:
        ~Y() {}
};

int main()
{
    X<int> A;
    X<float> B;
    Y *C = new Y;

    A.a = 12;
    B.a = 2.3;

    printf("A: %d; B: %f\n", A.a, B.a);

    A2 *a2 = new A2;
    a2->f();

    return 0;
}
4

5 に答える 5

6

はい、のようなものoperator newoperator delete実際には C ではなくC++ で定義されているため、C++ のランタイム ライブラリではなく、C のランタイム ライブラリにそれらを含めるのはばかげています (不正な呼び出しを明確に診断するために使用される「純粋な仮想」についても同じです)。純粋な仮想メソッドなど)。動的ライブラリ アクセスなしで実行可能ファイル全体をリンクする場合、リンカは (C++ ランタイム ライブラリがどのようにモジュール化されているかに応じて) コードで使用する標準 C++ ライブラリの最小限の部分を選択する必要があります (および使用する C++ 固有の機能が少ないほど (デストラクタ呼び出しのnew暗示などdelete)、ライブラリの大きなチャンクを取り込まないようにする可能性が高くなります;-)。

于 2010-09-15T02:13:11.433 に答える
6

多分この答えは少し遅すぎるかもしれませんが...

libstdc++ を使用せずに C++ プログラムを作成するのは簡単です。何十年もやっています。libstdc++ とのリンクは避けてください。それは簡単です。g++ の代わりに gcc をリンクに使用するか、偽の libstdc++ に new、del、および他のいくつかの関数のみを提供します。

基本的な libstdc++ 機能を malloc の透明なラッパーに置き換える方法の例を次に示します。

#include <stdlib.h>

// MSVC uses __cdecl calling convention for new/delete :-O
#ifdef _MSC_VER
#  define NEWDEL_CALL __cdecl
#else
#  define NEWDEL_CALL
#endif

extern "C" void __cxa_pure_virtual ()
{
    abort ();
}

void * NEWDEL_CALL operator new (size_t size)
{
    return malloc (size);
}

void * NEWDEL_CALL operator new [] (size_t size)
{
    return malloc (size);
}

void NEWDEL_CALL operator delete (void *p)
{
    if (p) free (p);
}

void NEWDEL_CALL operator delete [] (void *p)
{
    if (p) free (p);
}

void NEWDEL_CALL operator delete (void *p, size_t)
{
    if (p) free (p);
}

これをたとえば libstd--.cpp という名前のファイルに入れ、独自の libstdc++.a をビルドします。

gcc -c -O libstdc--.cpp
ar crs libstdc++.a libstdc--.o

次に、簡単なテストを試すことができます。

class A
{
    int *x;

public:
    A () { x = new int [10]; }
    ~A () { delete [] x; }
};

int main ()
{
    A a;
    return 0;
}

コンパイルして、リンクされているものを確認します。

g++ -g test.cpp -o テスト -L.

# ldd ./test
    linux-vdso.so.1 (0x00007ffed0b8d000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f4d18df0000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4d18bd9000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f4d18823000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4d1913b000)

ねえ、見て、お母さん、libstdc++ はありません!

別の方法として、g++ の代わりに gcc を使用してリンクし、リンカー コマンド ラインで libstdc--.o を指定することにより、偽の libstdc++ の使用を避けることができます。これにより、コードは置換ニュースと削除を見つけることができます。

于 2018-11-03T13:17:53.907 に答える
2

に対してリンクしてみてくださいlibsupc++.asupこれは、重い iostreams 関数などを含まない、裸の C++ポート ライブラリです。

確かではありませんが、これを使用するlibstdc++.aと、標準の第 1 項で定義されている「ホストされた」または完全な実装とは対照的に、「独立した」C++ 実装が得られると思います。

于 2010-09-15T02:36:29.077 に答える
1

ここに良い説明があります:

http://www.trilithium.com/johan/2005/06/static-libstdc/

この記事ではより詳細に説明していますが、これを行う主な理由の 1 つは、C++ 固有のライブラリがベースの libc のものよりも不安定になる傾向があることです。これにより、依存関係の問題が軽減される場合があります。

于 2010-09-15T02:10:53.147 に答える
0

別のアプローチは、プログラムを「統計化」することです。これは、すべてのライブラリを静的実行可能ファイルに埋め込むことを意味します。そうすれば、コードは、コンパイルに使用したマシンにあったglibcを常に使用します。必要なのは、実行中のマシンの互換性のあるカーネルだけです。私はそれを行うための2つのプログラムを知っています。1つはオープンソースです。

もう1つは商用ソフトウェアです。

もちろん、このアプローチには、たとえば、アプリケーションがバグを修正するために使用しているダイナミックライブラリを更新する場合などの欠点があります。これは、ライブラリが埋め込まれている実行可能ファイルでは、アプリケーションを再度コンパイルする必要があるためです。

于 2010-09-16T11:59:29.603 に答える