- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
请考虑以下代码和平:
// 1. Single header file. Imagine that it is some static library.
// Counter.h
#pragma once
struct Counter
{
Counter()
{
++getCount();
}
static int& getCount()
{
static int counter = 0;
return counter;
}
};
// 2. Shared library (!) :
// main_DLL.cpp
#include <iostream>
#include "counter.h"
extern "C"
{
__declspec(dllexport) // for WIN
void main_DLL()
{
Counter c;
std::cout << "main_DLL : ptr = " << &Counter::getCount()<< " value = " << Counter::getCount() << std::endl;
}
}
// 3. Executable. Shared library statically (!) linked to the executable file.
// main.cpp
#include "counter.h"
#include <iostream>
extern "C"
{
__declspec(dllimport) // for WIN
void main_DLL();
}
int main()
{
main_DLL();
Counter c;
std::cout << "main_EXE : ptr = " << &Counter::getCount() << " value = " << Counter::getCount() << std::endl;
}
结果:
Results for WIN (Win8.1 gcc 5.1.0):
main_DLL : ptr = 0x68783030 value = 1
main_EXE : ptr = 0x403080 value = 1
// conclusion: two different counters
Results for UNIX (Red Hat <I don’t remember version exactly> gcc 4.8.3):
main_DLL : ptr = 0x75693214 value = 1
main_EXE : ptr = 0x75693214 value = 2
// conclusion: the same counter addressed
建筑:
Building for WIN:
g++ -c -Wall -Werror -o main_DLL.o main_DLL.cpp
g++ -shared -Wl,--out-implib=libsharedLib.a -o libsharedLib.so main_DLL.o
g++ -Wall –Werror -o simpleExample main.cpp -L./ -lsharedLib
Building for UNIX:
g++ -c -Wall -Werror -fPIC -o main_DLL.o main_DLL.cpp
g++ -shared -fPIC -o libsharedLib.so main_DLL.o
g++ -Wall –Werror -fPIC -o simpleExample main.cpp -L./ -lsharedLib
因此,您看到我在 UNIX 上添加了 –fPIC 并且不需要为 UNIX 创建导入库,因为所有导出符号都包含在共享库中。在 Windows 上,我为此使用 __declspec。
对我来说,Windows 上的结果非常令人期待。因为共享库和可执行文件是分开构建的,所以它们应该知道 Counter::getCount 中的静态变量。他们应该简单地为其分配内存,这就是为什么他们有不同的静态计数器。
我使用 nm、objdump 等工具进行了相当多的分析。虽然我不是他们的大专家,所以我没有发现任何可疑之处。如果需要,我可以提供他们的输出。
使用 ldd 工具我可以看到在这两种情况下静态链接的库。
为什么我在 Unix 上看不到相同的结果,这很奇怪。根本原因可能在于构建选项(例如 –fPIC),还是我遗漏了什么?
最佳答案
在 Windows 中,除非您添加 dllexport
语句,否则 DLL 不会导出全局和静态符号,因此,链接器甚至不知道它们的存在,因此它会为静态成员分配新的实例.
在 linux/unix 中,共享库导出所有全局和静态符号,因此当链接器发现共享库中存在静态成员时,它只使用其地址。
这就是不同结果的原因。
关于c++ - 当使用静态成员将共享库静态链接到可执行文件时,我在 UNIX 和 WIN 上收到不同的结果。请解释为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31495877/
我正在开发一个 voip 调用应用程序。我需要做的是在接到来电时将 Activity 带到前台。我在应用程序中使用 Twilio,并在收到推送消息时开始调用。 问题是我试图在接到任何电话时显示 Act
我是一名优秀的程序员,十分优秀!