在DLL中使用全局变量的疑问?

lifeforu 2005-12-24 08:29:42
在一个DLL中用到2个类,大致结构如下:
//A.cpp
#include "b.h"
ClassB g_b;
A:A()
{
...
g_b.doSomeThing();
}
//B.cpp
B:B()
{
TRACE("b.constructor");
}
B:doSomething()
{
TRACE("b.dosomething.");
}

//大致结构如此,该类在Application中使用良好
但是在DLL中调用顺序却是
b.dosomething
b.constructor
也就是说构造函数在其后执行,何故?DLL的机制?
...全文
306 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
lifeforu 2005-12-27
  • 打赏
  • 举报
回复
to xiaoqiqixiao(七七) 我觉得奇怪是因为CClassB g_classB;作为一个全局变量出现.

我想这个问题主要原因还是在CTestDllGlobalApp theApp;作为一个全局变量在CClassB g_classB之前...或者是由编译顺序决定了这个现象的出现.


还有一个很重要的问题是使用BoundCheck的问题

是不是每一个错误报告都是正确的?我的程序报好几个错误,都定位在C++类库源码上面
例如:

Invalid argument strlen,argument 1,LPSTR:0x1002D324
function::std::char_traits<char>::length()
我分析是一个使用string作为参数的函数调用,我直接做了doSomething("hello");这样的.

memory leak
40 bytes allocated by operator_new local0.cpp(55),HANDLE 0x01164948
function:std::locale::_Init()
这样的就无从下手了

还有一些resource leak
Resource leak:allocated by InitializeCriticalSection in xlock.cpp(50)
std::_Lockit::_Lockit()
这样的也是我的程序有问题吗?

以前记得有一贴子说他们公司的客户只认boundcheck,要是有错误就不通过,是怎么做到的?
lifeforu 2005-12-26
  • 打赏
  • 举报
回复
谁有空试试?或是留下mail我把测试文件发过来?

很奇怪了.............
James0001 2005-12-26
  • 打赏
  • 举报
回复
我写的。在exe里调用Stub,dll里断点顺序没错。

class clsB
{
public:
clsB() {
__debugbreak();
}
void something(void) {
__debugbreak();
}
} tmpB;

class clsA
{
public:
clsA() {
tmpB.something();
}
};

__declspec(dllexport) void __stdcall Stub(void)
{
clsA a;
return;
}
softrain 2005-12-26
  • 打赏
  • 举报
回复
应该是你先声明了a对象再声明的b对象,那么肯定先调用a的构造,再调用b的构造.
至于在b构造之前调用b的函数,应该是编译时就直接把对b的该函数地址的调用直接放到a的构造函数中了.
pomelowu 2005-12-26
  • 打赏
  • 举报
回复
没有问题,classB的确是在它的Initialize之后构造的。
我的理解是,虽然全局变量是在代码执行以前构造,但是全局变量也是有作用域的,那就是整个文件。对于ClassA.cpp来说,A的构造函数是显式被调用的,所以它是整个文件最开始被执行的单元,然后才发现这个ClassA.cpp中还有个全局对象g_classB需要构造。

你把
CClassB g_classB;
变为
extern CClassB g_classB;
然后在你的TestDllGlobal.cpp 中加上
CClassB g_classB;
看看效果呢
xiaoqiqixiao 2005-12-26
  • 打赏
  • 举报
回复
这好象没什么不可理解的吧,你先调用class A的构造函数,再调用class B的构造函数,你的
class B的initialize又在class A的构造函数中调用,这很正常啊
为什么你会觉得奇怪呢
lifeforu 2005-12-25
  • 打赏
  • 举报
回复
是的,当时就是这样

lifeforu 2005-12-25
  • 打赏
  • 举报
回复
很奇怪,我把这个全局变量作为A的static变量也是这样

不明白了...
sboom 2005-12-25
  • 打赏
  • 举报
回复
ClassA.Constructor
ClassB.Initialize(100)//--如果把这行去掉似乎合理
ClassB.Constructor
ClassB.Initialize(200)
ClassB.Destructor
ClassA.Destructor
lifeforu 2005-12-25
  • 打赏
  • 举报
回复
// ClassA.h: interface for the CClassA class.
#if !defined(AFX_CLASSA_H__E3D9DC1B_345B_436A_AE87_F2128BC178F2__INCLUDED_)
#define AFX_CLASSA_H__E3D9DC1B_345B_436A_AE87_F2128BC178F2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "ClassB.h"
class CClassA
{
public:
CClassA();
virtual ~CClassA();
int TestIndex(int nLen);
};

#endif
---------------------------------------------------------------------------
// ClassA.cpp: implementation of the CClassA class.
#include "stdafx.h"
#include "TestDllGlobal.h"
#include "ClassA.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// Construction/Destruction
CClassB g_classB;

CClassA::CClassA()
{
TRACE("ClassA.Constructor\n");
g_classB.Initialize(100);
}

CClassA::~CClassA()
{
TRACE("ClassA.Destructor\n");
}
int CClassA::TestIndex(int nLen)
{
g_classB.Initialize(nLen);
return 1;
}
---------------------------------------------------------------------------
// ClassB.h: interface for the CClassB class.

#if !defined(AFX_CLASSB_H__0CA7CCAB_0072_47A3_8083_5DBA1B4B003C__INCLUDED_)
#define AFX_CLASSB_H__0CA7CCAB_0072_47A3_8083_5DBA1B4B003C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CClassB
{
public:
CClassB();
virtual ~CClassB();
void Initialize(int nIndex);

};

#endif
----------------------------------------------------------------
// ClassB.cpp: implementation of the CClassB class.
#include "stdafx.h"
#include "TestDllGlobal.h"
#include "ClassB.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// Construction/Destruction

CClassB::CClassB()
{
TRACE("ClassB.Constructor\n");
}

CClassB::~CClassB()
{
TRACE("ClassB.Destructor\n");
}
void CClassB::Initialize(int nIndex)
{
TRACE("ClassB.Initialize(%d)\n" , nIndex);
}
----------------------------------------------------
// TestDllGlobal.h : main header file for the TESTDLLGLOBAL DLL

#if !defined(AFX_TESTDLLGLOBAL_H__866F97AA_E0C9_4458_BDC9_79D01D0B1F16__INCLUDED_)
#define AFX_TESTDLLGLOBAL_H__866F97AA_E0C9_4458_BDC9_79D01D0B1F16__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h" // main symbols
#include "ClassA.h"

class CTestDllGlobalApp : public CWinApp
{
public:
CTestDllGlobalApp();
CClassA m_classA;
DECLARE_MESSAGE_MAP()
};


#endif
------------------------------------------------------------------------------
// TestDllGlobal.cpp : Defines the initialization routines for the DLL.

#include "stdafx.h"
#include "TestDllGlobal.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTestDllGlobalApp

BEGIN_MESSAGE_MAP(CTestDllGlobalApp, CWinApp)
//{{AFX_MSG_MAP(CTestDllGlobalApp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTestDllGlobalApp construction

CTestDllGlobalApp::CTestDllGlobalApp()
{
}

CTestDllGlobalApp theApp;


extern "C" BOOL PASCAL EXPORT TestIndex( int nLen)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

theApp.m_classA.TestIndex(nLen);

return TRUE;
}
----------------------------------------------------------
以上为动态链接库文件,并将部分注释去掉,是不是theApp.m_classA这种做法不正确?
以下为调用代码:
void CTestDllDlg::OnButton1()
{
HINSTANCE hmod = ::LoadLibrary("TestDllGlobal.dll");
if(hmod == NULL)
{
MessageBox("load dll failed." , "MSG" , MB_OK);
return ;
}
typedef BOOL (WINAPI*TestIndexProc)( int nLen);
TestIndexProc pPorc = (TestIndexProc)GetProcAddress(hmod , "TestIndex");
if(pPorc)
(*pPorc)(200);
::FreeLibrary(hmod);
}
-------------------------------------------------------------
以下为TRACE输出
ClassA.Constructor
ClassB.Initialize(100)
ClassB.Constructor
ClassB.Initialize(200)
ClassB.Destructor
ClassA.Destructor
The thread 0x8B4 has exited with code 0 (0x0).
--------------------------------------------------------------
环境:Win2000(SP4.2195)+VC6.0(SP6)
sboom 2005-12-25
  • 打赏
  • 举报
回复
怪异,贴完整代码?
DentistryDoctor 2005-12-25
  • 打赏
  • 举报
回复
不大可能吧。
lifeforu 2005-12-24
  • 打赏
  • 举报
回复
goodboyws(深夜不眠者):
还会有两次constructor?
goodboyws 2005-12-24
  • 打赏
  • 举报
回复
估计是第一个TRACE("b.constructor");没有显示出来,写文件试试

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧