- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
环境:linux x64,编译器gcc 4.x
项目结构如下:
static library "slib"
-- inside this library, there is static object "sobj"
dynamic library "dlib"
-- links statically "slib"
executable "exe":
-- links "slib" statically
-- links "dlib" dynamically
在程序结束时,“sobj”被破坏了两次。这种行为是预期的,但它在相同的内存地址被破坏了两次,即析构函数中的相同“this” - 结果存在双重破坏问题。我认为这是由于某些符号重叠。
该冲突的解决方案是什么?也许一些链接选项?
这里是测试用例:
main_exe.cpp
#include <cstdlib>
#include "static_lib.h"
#include "dynamic_lib.h"
int main(int argc, char *argv[])
{
stat_useStatic();
din_useStatic();
return EXIT_SUCCESS;
}
static_lib.h
#ifndef STATIC_LIB_H
#define STATIC_LIB_H
#include <cstdio>
void stat_useStatic();
struct CTest
{
CTest(): status(isAlive)
{
printf("CTest() this=%d\n",this);
}
~CTest()
{
printf("~CTest() this=%d, %s\n",this,status==isAlive?"is Alive":"is Dead");
status=isDead;
}
void use()
{
printf("use\n");
}
static const int isAlive=12385423;
static const int isDead=6543421;
int status;
static CTest test;
};
#endif
static_lib.cpp
#include "static_lib.h"
CTest CTest::test;
void stat_useStatic()
{
CTest::test.use();
}
dynamic_lib.h
#ifndef DYNAMIC_LIB_H
#define DYNAMIC_LIB_H
#include "static_lib.h"
#ifdef WIN32
#define DLLExport __declspec(dllexport)
#else
#define DLLExport
#endif
DLLExport void din_useStatic();
#endif
dynamic_lib.cpp
#include "dynamic_lib.h"
DLLExport void din_useStatic()
{
CTest::test.use();
}
CMakeLists.txt
project( StaticProblem )
cmake_minimum_required(VERSION 2.6)
if(WIN32)
else(WIN32)
ADD_DEFINITIONS(-fPIC)
endif(WIN32)
ADD_LIBRARY( static_lib STATIC static_lib.cpp static_lib.h)
ADD_LIBRARY( dynamic_lib SHARED dynamic_lib.cpp dynamic_lib.h)
TARGET_LINK_LIBRARIES( dynamic_lib static_lib )
ADD_EXECUTABLE( main_exe main_exe.cpp )
TARGET_LINK_LIBRARIES( main_exe static_lib dynamic_lib )
该示例在 Windows 上运行正常,但在 linux 上 - 存在问题。由于它在 Windows 上运行良好,解决方案应该像更改一些链接选项或类似的东西,但不更改项目结构或不使用静态变量。
输出:
window
CTest() this=268472624
CTest() this=4231488
use
use
~CTest() this=4231488, is Alive
~CTest() this=268472624, is Alive
Linux
CTest() this=6296204
CTest() this=6296204
use
use
~CTest() this=6296204, is Alive
~CTest() this=6296204, is Dead
最佳答案
TL;DR:您不应该将一个库链接一次作为静态依赖项和一次作为动态依赖项。
How are the destructors of static variables executed in the Itanium ABI (used by clang, gcc, icc...)?
C++ 标准库提供了一种标准工具,用于在程序关闭期间(在 main 结束后)以atexit
的格式安排函数的执行。
行为比较简单,atexit
基本上是构建了一个回调栈,因此会按照它们调度的reverse顺序执行。
每当构造一个静态变量时,在其构造结束后,立即在 atexit
堆栈中注册一个回调以在关闭期间将其销毁。
What happens when a static variable exists both in a statically linked library and a dynamically linked library?
它尝试存在两次。
每个库都会有:
令人惊讶的是符号解析在加载器中的工作方式。本质上,加载器在符号和位置(指针)之间建立映射,先到先得。
但是,加载/卸载部分是无名的,因此它们中的每一个都是完整执行的。
因此:
So what?
解决方案很简单:不链接到静态库 A(直接)和动态库 B 也链接到 A(动态或静态)。
根据用例,您可以:
As it works OK on windows, solution should be like change some linking option or something like that, but not change project structure or not use static vars.
万一您确实需要静态变量的两个独立实例,除了重构代码之外,还可以在动态库中隐藏符号。
这个 Windows 的默认行为,这就是为什么那里需要 DLLExport
属性,以及为什么因为 CTest::test
忘记了它,所以 Windows 上的行为不同.
但是请注意,如果您选择这种行为,该项目的任何 future 维护者都会大声诅咒您。没有人希望静态变量有多个实例。
关于c++ linux双重销毁静态变量。链接符号重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6714046/
当你有一个对象 OBJ1 包含一个关键部分 CS 和一个指向另一个对象 OBJ2 的指针时,我无法弄清楚什么是正确的关闭过程 假设您有两个函数 A 和 B。 A进入临界区,修改OBJ2中的数据后离开临
我有一个成员变量声明为 CComPtr m_spXMLDoc; XML 文档是这样创建的 CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC
在我的工作平台中,我遇到了 session_destroy 问题 function logout() { $_SESSION['id'] = ''; session_destroy(); } 在这
如何使用 destroy 删除 jScrollPane。请您给出以下代码的简单示例: $(document).ready(function() { $(".div1").jScrollPane
这是我在这里发表的第一篇文章,但我想对社区表示感谢,因为通过来到这里并在已经得到解答的问题中找到解决方案,我已经无数次找到了问题的解决方案。 话虽这么说,我想进入正题。我正在 Code Gear 的
我在导航 View 中工作。在此导航 View 中,您可以偶然发现个人资料页面。在此个人资料页面中,您可以看到与当前个人资料相关的其他个人资料(基本上是数据 View 中显示的图片)。您可以通过点击这
我想销毁项目中的 session ,这样当我单击“注销”时,它会转到页面“KillSession.jsp”,在该文件中我编写了“session.invalidate();”然后我将用户重定向到登录页面
我有关于 Thread 的 2 问题,我只是想澄清一些事情。使用以下代码: public class MyThread implements Runnable { Boolean StopTh
我遇到了内存泄漏,代码类似于下面的代码(这是每个循环都有不同输入的模拟)。 问题 对象 Object_XXX 非常复杂,它与数据库以及其他填充了数据库数据的对象有连接。 for(int i=0
当我在 Python 中启动一个类时,我给它一些值。然后我调用类中执行某些操作的方法。这是一个片段: class TestClass(): def __init__(self):
我想删除所有 div、类、属性和几乎所有 CKEDITOR 添加到 DOM 的内容。例如调用 jquery tabs("destroy");将删除所有由 jQuery 选项卡添加的 div。我怎样才能
我想清除析构函数中的一个映射,但我不知道它是否为空。如果我按如下方式清除它可以吗? for(std::map::iterator it = m_map.begin(); it != m_map.end
我正在尝试克隆 TikTok 应用。对于主屏幕,我制作了一个 VerticalViewPager(自定义 View 分页器),其中包含“点赞”按钮、标题和评论。我正在从 Firebase 检索视频。
我正在制作自己的游戏。目标之一是在世界中拥有尽可能多的物体。在这个游戏中,需要在一些不可预测的时间段内创建许多对象(比如武器开火会创建一个对象),一旦该弹丸击中某物,该对象也需要被摧毁(也许它击中的东
有没有办法在 JavaScript 中破坏 HTML5 WebWorker? 这是我的情况:我有一个 Web 应用程序生成相当数量的 WebWorker(在 16 到 32 之间的任何地方)来优化一些
如何销毁 php 中的 session ? 事情是当用户点击注销按钮时, session 将结束,他将被重定向到 index.php 这是我的代码 客户.php 这是来自用户想要再次登录的 ind
关于 GtkBuilder 的问题。 当我们取消引用构建器指针时,它是否会破坏构建器创建的所有屏幕/小部件? if( builder_ptr ) g_object_unref(G_OBJECT
有没有办法销毁 WebView 实例?如果页面加载,并说视频开始播放,我希望能够,当我隐藏 WebView 时,基本上可以销毁它,或者至少重置它。 我知道我可以听 visibleProperty 并执
我有一组可拖动的元素。如何删除可拖动功能? $('.draggable').draggable('disable') 在我的情况下不是一个选项 $('.draggable').draggable('d
下面的代码会抛出一个 EZDecompressionError 消息 'Invalid ZStream operation' 每当行 Reader.Free 被执行。有人可以告诉我这段代码有什么问题吗
我是一名优秀的程序员,十分优秀!