2

CentOS 6.5で遭遇しました。私がオンラインで検索したように、動的ライブラリを使用する場合、静的変数は Windows と Linux で異なる動作をします。つまり、次のように、Windows では変数の重複が発生しますが、Linux では発生しません

しかし、これを検証する小さなプログラムを書いたところ、Linux でも重複が発生することがわかりました。4 つのファイルを含む小さなプログラムを次に示します。

(1) ああ

#ifndef A_H
#define A_H
#include <cstdio> 
static int b; 
extern "C" class A { 
    public:
    int mem;
    A() {
        printf("A's address: %p\n", this);
        printf("B's address: %p\n", &b);
    }
    void print() {
        printf("%p: %d\n", this, mem);
    }
    ~A() {
        printf("DELETE A!!!!! %p\n", this);
    }
}; 
extern A a;
#endif

(2) A.cpp

#include "A.h"
A a;

(3) d.cpp

#include "A.h"
extern "C" void exec() {
    a.print();
}

(4) main.cpp

#include "A.h"
#include <dlfcn.h>
typedef void (*fptr) ();
int main() {
    a.mem = 22;
    a.print();
    void *handle;
    handle = dlopen("d.so", RTLD_LAZY);
    fptr exec = reinterpret_cast<fptr>(dlsym(handle, "exec"));
    (*exec)();
    dlclose(handle);
    return 0;
}

プログラムをコンパイルして実行する方法は次のとおりです。

g++ d.cpp A.cpp -shared -rdynamic -o d.so -ldl -I. -fPIC -g -std=c++1y
g++ main.cpp A.cpp -ldl -I. -g -std=c++1y
./a.out

動的部分d.cppと静的部分の両方で、およびで宣言されmain.cppた変数aおよび を使用します。そして、これが私のマシンでのプログラムの結果です。bA.cppA.h

A's address: 0x600f8c
B's address: 0x600f90
0x600f8c: 22
A's address: 0x7fb8fe859e4c
B's address: 0x7fb8fe859e50
0x7fb8fe859e4c: 0
DELETE A!!!!! 0x7fb8fe859e4c
DELETE A!!!!! 0x600f8c

aグローバル変数と静的変数のアドレスbは動的部分と静的部分で同じでなければならないので、これは私を大いに驚かせます。またa、静的部分の変更は動的部分には影響しないようaです。誰かが私の質問に答えてくれますか、またはプログラムの間違いを見つけるのを手伝ってくれますか?

ところで、正直なところ、私が取り組んでいる別のプロジェクトでは、動的ライブラリと静的ライブラリでグローバル変数のアドレスが同じであることがわかりました。しかし、そのプロジェクトは大きすぎるため、動作を再現するための小さなプログラムを提供することはできません。

どうもありがとう !

4

1 に答える 1

0

最初に示したコマンドは、共有オブジェクトを構築しますd.so。あなたの質問の文脈に基づいて、あなたもリンクするつもりだったと思いd.soますが、2番目のコマンドにはその部分が欠けているようです。これは、あなたが示したプログラム出力の唯一の説明であるため、タイプミスであると想定しています。これは、A.cpp直接リンクされており、ライブラリにも組み込まれていますd.so

それを考えると、あなたがリンクした記事から引用します:

両方で使用されるオブジェクト コード ルーチンは、それぞれで複製しないでください。これは、シングルトン クラスなどの静的変数を使用するコードに特に当てはまります。静的変数はグローバルであるため、一度しか表すことができません。2 回含めると、予期しない結果が生じます。

しかし、それはまさにあなたが破っているように見えるルールです。Aクラスの静的スコープのインスタンスを 2 回、d.soおよびメインのアプリケーション実行可能ファイルで表しています。

したがって、それは示された結果のようです:「予期しない結果」。

于 2015-11-10T03:16:58.730 に答える