以下是我的代码......
的main.cpp
/* header files are included here */
PCI_card card;
int main(void)
{
card.init_card(0);
return 0;
}
pci_card.h
#ifndef __PCI_CARD_H
#define __PCI_CARD_H
/* header files are included here */
typedef struct {
int32_t card_index;
int32_t user_counter;
} card_dev_t;
class PCI_card {
public:
PCI_card() : dev_descriptor(-1) { enlarge_vector(); }
int32_t init_card(int32_t card_num);
private:
int32_t dev_descriptor;
public:
static int32_t enlarge_vector();
private:
static int32_t card_amount;
static std::vector<card_dev_t> cards;
};
#endif
pci_card.cpp
/* header files are included here */
int32_t PCI_card::card_amount = -1;
std::vector<card_dev_t> PCI_card::cards;
int32_t PCI_card::init_card(int32_t card_num)
{
if (card_num >= card_amount || card_num < 0)
return -1;
card_dev_t new_card = {
.card_index = card_num,
.user_counter = 1
};
cards[card_num] = new_card;
dev_descriptor = card_num;
return 0;
}
int32_t PCI_card::enlarge_vector()
{
card_amount = 10;
card_dev_t null_card = {
.card_index = -1,
.user_counter = -1
};
cards.resize(card_amount, null_card);
return card_amount;
}
在 main.cpp 中,card
被定义为全局变量,当然,它应该在调用main()
函数之前初始化,这可以清楚地看到通过 gdb 。
初始化card
时,调用类PCI_card
的构造函数,根据cards
成员变量调整此类中的向量card_amount
。从gdb开始,这个向量可以正确初始化,它包含10个元素。
在调用main()
函数之前发生了奇怪的事情,向量被重置。在gdb中,向量的大小回滚到0,当然,后续操作(例如下标此向量)会导致段错误。
我不知道这里发生了什么......这太荒谬了......
答案 0 :(得分:0)
看起来你已经点击了static initialization order fiasco。 PCI_card card;
之前std::vector<card_dev_t> PCI_card::cards
初始化可能会发生。如果发生这种情况(并且标准允许),那么PCI_card::enlarge_vector()
将在尚未初始化的向量上调用resize(此处输入UB)。执行后,PCI_card::cards
的正常静态初始化将被执行 - 将向量初始化为空的初始化。这就是你看到这种行为的原因:
在gdb中,向量的大小回滚到0,
这是未定义的行为,因此您在gdb中看到的任何内容都是可能的。
解决方法是使卡片非静态,或者使用带静态字段的静态函数将其返回:
std::vector<card_dev_t>& getCards() {
static std::vector<card_dev_t> cards;
return cards;
}
这将确保在cards
getCards.