extern全局对象似乎没有初始化其成员

时间:2014-07-15 21:52:31

标签: c++

我在执行此代码时遇到了段错误。特别是在调用g_lru_stack.add_node(& lru_node)之后。

在GDB下运行表明虚拟节点看起来不像是已经初始化了。这与extern全局变量的初始化有关吗?如果有的话,我们将非常感谢您的帮助。

我已经在header和cpp文件中包含了片段。

具体来说,我的问题是: 如何获取在object.cc顶部声明的LRU_Stack g_lru_stack来调用不带参数的LRU_Node ctor。

似乎这个ctor永远不会被调用,因此为什么我的虚节点没有被初始化。

Object.h

class obj_payload;
extern cas_mutex g_lru_stack_mutex;


class LRU_Node {

private:
        obj_payload* payload;
    LRU_Node* up;
    LRU_Node* down;
    size_t predicted_bytes_in_cache;

public:
    LRU_Node() : payload(nullptr), up(this), down(this), predicted_bytes_in_cache(1337) {}      // Dummy ctor

    LRU_Node(obj_payload* p) : payload(p), up(nullptr), down(nullptr), predicted_bytes_in_cache(88) {} // Normal Creation of node

    //Adds a node to the top of the stack
    //Has dummy context
    void add_to_stack(LRU_Node* newNode);

    //Sets how many bytes of the object are predicted to be in the cache
    //Has dummy context
    void is_node_in_cache(LRU_Node* node);

    //Moves a node to the top of the stack
    //Has dummy context
    void move_node_to_top(LRU_Node* node);

    //Has context of caller
    size_t get_predicted_bytes_in_cache();
};

class LRU_Stack {
    LRU_Node dummy;

public:
void add_node(LRU_Node* node);

void move_node_to_top(LRU_Node* node);
};
extern LRU_Stack g_lru_stack;



class obj_payload {
    typedef uint32_t ctr_t;
private:
    ctr_t refcnt;
    const uint32_t sz;                // size of the data space in bytes
    LRU_Node lru_node;                // Jordan -- This arg objects node for the LRU_Stack


    obj_payload( typeinfo tinfo_,
         uint32_t size_,
         int refcnt_init=1 )
    : refcnt( refcnt_init ),
      sz( size_ ),
      tinfo( tinfo_ ), lru_node(this) {

        g_lru_stack.add_node(&lru_node);    


    }

Object.cc

#include "object.h"

namespace obj {

//Jordan -- Global LRU_Node Stack 
cas_mutex g_lru_stack_mutex;
LRU_Stack g_lru_stack;

//Adds a node to the top of the stack
//Has dummy context
void LRU_Node::add_to_stack(LRU_Node* newNode) {  
        newNode->down = down;           // Set the new nodes previous -> dummys previous
        newNode->up = this;         // Set new nodes next -> dummy
        down->up = newNode;         // Dummy next -> new node (i.e. Previous top of stack node up -> newNode)
        down = newNode;             // Dummy previous -> new node (i.e. Dummy down pointer now links back round to the new node at the top)
}

//Sets how many bytes of the object are predicted to be in the cache
//Has dummy context
void LRU_Node::is_node_in_cache(LRU_Node* node) {
        size_t total = 0;
        LRU_Node* orignal = node;

        while (node != this) {
                total += node->payload->get_size(); // Add current size to total
                node = node->up;                        // Go to next node
        }
        node = orignal; //Reset node to the passed in node, then set how many bytes it has contained within cache

        if (total <= cache_size) {
                node->predicted_bytes_in_cache = node->payload->get_size();
        }
        else {
                node->predicted_bytes_in_cache = (node->payload->get_size()) - (total - cache_size) < node->payload->get_size() ? (node->payload->get_size()) - (total - cache_size) : 0;
        }
}

//Moves a node to the top of the stack
//Has dummy context
void LRU_Node::move_node_to_top(LRU_Node* node) {

        if (down != node) { // Check that the node to move is not already top of stack
                node->down->up = node->up;
                node->up->down = node->down;

                if (down == node->up) { // If the node is seccond top of stack 
                        node->up->up = node;
                }

                node->down = down;
                node->up = this;
                down->up = node;
                down = node;
        }
}

//Has context of caller
size_t LRU_Node::get_predicted_bytes_in_cache() {
        return predicted_bytes_in_cache;
}

//Has dummy context
bool LRU_Node::is_empty() {
        return (up == this);
}

void LRU_Stack::add_node(LRU_Node* node) {
    g_lru_stack_mutex.lock();
    dummy.add_to_stack(node);
    g_lru_stack_mutex.unlock();
}

void LRU_Stack::move_node_to_top(LRU_Node* node) {
    g_lru_stack_mutex.lock();
    dummy.is_node_in_cache(node);
    dummy.move_node_to_top(node);
    g_lru_stack_mutex.unlock();
}

1 个答案:

答案 0 :(得分:2)

&#34; extern globals&#34;不是对象(除非它们包含初始值设定项):它们是前向声明。

全局对象分两个阶段初始化:

  • 所有那些使用编译时常量初始值设定项的人都完成了,剩下的就归零了。
  • 运行时初始值设定项按对象定义的顺序运行。 (对于不同编译单元中的对象没有排序保证!)。

好像UB让你在那里。

要解决错误,请执行以下操作之一:

  • 在第一次使用之前将对象的定义放在同一个编译单元中(最有效的方法)。
  • 将对象作为静态放入访问器函数中。 Init将首次使用(线程安全!)。

    Type& getTypeSingleton() {
        static Type x/*optional initializer*/;
        return x;
    }
    
  • (取决于实现)在命令行中首先提到的编译单元将在所有当前实现中首先初始化(尽管第一个很有效但很脆弱)。