2013-11-21 183 views
1

我遇到了以下奇怪的情况:我设法有一个全局静态变量与两个实例...这是正常的,或者这是一个编译器中的错误,或者这是一个C++的隐藏领域?下面的复制是一个较大项目的摘录(其行为相同),显然名称已更改以保护罪魁祸首(并且是的,我知道此代码中存在内存泄漏)。C++静态变量多个实例

这里谈到的代码:

// other.h 
#ifndef _OTHER_H_ 
#define _OTHER_H_ 

struct other 
{ 
    long longer; 
    int inter; 
    char charer; 
}; 

void dosomething(); 

#endif 

而且

// other.cpp 
#include "other.h" 
#include "util.h" 

void dosomething() 
{ 
    other* something = alloc_mem(other, 4); 
} 

而且

// util.h 
#ifndef _UTIL_H_ 
#define _UTIL_H_ 

#include <memory.h> 
#include <string> 

#include "test_class.h" 

template <class T> T* allocate(size_t count, const char* f, long l, const char* sth) 
{ 
    T* tmp = new T[count]; 
    memset(tmp, 0, count * sizeof(T)); 
    test_class<T*>::instance().throwIn(tmp, f, l, sth, count); 

    return tmp; 
} 

#define alloc_mem(type,count) allocate<type>(count, __FILE__, __LINE__, (char*)0) 

#endif 

而且

// main.cpp 
#include "other.h" 
#include "util.h" 

int main() 
{ 
    int* i = alloc_mem(int, 1); 
    int* i1 = alloc_mem(int, 20); 
    char* c = alloc_mem(char, 1); 

    dosomething(); 
    int* i3 = alloc_mem(int, 1); 
} 

与主要部分:

// test_class.h 
#ifndef test_class_H 
#define test_class_H 
#include <stdlib.h> 
#include <iostream> 
#include <typeinfo> 
#include <cxxabi.h> 

static long int all_alloc = 0; // THIS will get linked in two times! 

template <typename T> 
class test_class 
{ 
private: 
    test_class() {} 
    static test_class<T>* pinstance; 

public: 
    ~test_class() {} 
    static test_class& instance() { 
     if(pinstance == NULL) { 
      pinstance = new test_class(); 
     } 
     return *pinstance; 
    } 

    void throwIn(T item, const char* file, long line, const char* _compiler, long count) { 
     int status; 
     char* s = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status) ; 
     std::cout << "request:" << sizeof(T) * count << " bytes, type:" << s << " @ "<< 
       file << ":" << line << " global_addr:" << &all_alloc << std::endl; 
     all_alloc += sizeof(T) * count ; 
     free(s); 
     std::cout<<"All memory:" << all_alloc << std::endl; 
    } 
}; 

template <class T> test_class<T>* test_class<T>::pinstance = NULL; 

#endif 

所以,你必须编译此为:

g++ main.cpp other.cpp -o test 

和运行它,然后:

$ ./test 
request:8 bytes, type:int* @ main.cpp:6 global_addr:0x6022d8 
All memory:8 
request:160 bytes, type:int* @ main.cpp:7 global_addr:0x6022d8 
All memory:168 
request:8 bytes, type:char* @ main.cpp:8 global_addr:0x6022d8 
All memory:176 
request:32 bytes, type:other* @ other.cpp:6 global_addr:0x6022f8 
All memory:32 
request:8 bytes, type:int* @ main.cpp:11 global_addr:0x6022d8 
All memory:184 

如此,因为我可以看到一个相当大的惊喜,我有两个全局地址all_alloc ...事实上,nm -C test显示:

00000000006022d8 b all_alloc 
00000000006022f8 b all_alloc 

所以,很明显的问题:

为什么?这怎么可能?有什么东西允许这种行为,或者这是编译器或链接器中的某处的错误吗?

+0

这个“test_class.h”直接位于静态问题的上方,这是一个相当强的指标,它位于标题中,并且命令行提示两个源文件包含它,每个源文件都获得它们自己的'all_alloc'。包含'test_class.h'的每个文件都将获得自己的'all_alloc'。 – WhozCraig

+0

这不是问题,但是以下划线开头的名称后跟大写字母('_OTHER_H_')和包含两个连续下划线的名称将保留给实施。不要使用它们。 –

回答

4

在这种情况下,我认为您不想声明all_alloc静态。在这种情况下,这意味着联动是内部的。在你的情况下,你会得到两个副本,因为两个文件包含标题。

如果您删除static,那么您将有两个副本冲突,并导致链接器错误。哪个不好。

我相信你想要做的就是把static改为extern,然后在一个 cpp文件中定义变量及其值。

头:

extern long int all_alloc; 

CPP:

long int all_alloc = 0; 

这将提供的是你的代码共享all_alloc一个副本。

0

当你有全局变量它已经有了静态持续时间,所以static关键字意味着它有所不同。当你在文件中定义了你的全局静态变量时,我认为这是一个头文件。为什么在标题中使用静态全局变量是个不好的主意,你会得到什么你可以阅读here 所以答案是:它是预期的行为,而不是一个错误。