2010-02-01 69 views
0

我遇到了使用vector.push_back(value)覆盖最终值而不是追加到最后的问题。为何会发生这种情况?我在矢量中有一个样本项,所以它的大小从未达到零。下面是代码..std :: vector覆盖最终值,而不是增长?

void UpdateTable(vector<MyStruct> *Individuals, MyStruct entry) 
{ 
    MyStruct someEntry; 
    bool isNewEntry = true; 

    for (int i = 0; i < Individuals->size(); i++) 
    { 
     if (!(strcmp(Individuals->at(i).sourceAddress, entry.sourceAddress))) 
     { 
      isNewEntry = false; 
      //snip. some work done here. 
     } 
    } 

    if(isNewEntry) 
    { 
     Individuals->push_back(entry); 
    } 
} 

这让我的第一个“示例”值留在,并将只允许向量中的一个项目。当添加2个新条目时,第二条将覆盖第一条,因此大小永远不会大于2.

编辑:更多代码,因为这显然不是问题?

void *TableManagement(void *arg) 
{ 
     //NDP table to store discovered devices. 
     //Filled with a row of sample data. 
     vector<MyStruct> discoveryTable; 
     MyStruct sample; 
     sample.sourceAddress = "Sample"; 
     sample.lastSeen = -1; 
     sample.beaconReceived = 1; 
     discoveryTable.push_back(sample); 

     srand(time(NULL)); 
     while(1) 
     { 
      int sleepTime = rand() % 3; 
      sleep(sleepTime); 
      MyStruct newDiscovery = ReceivedValue(); 
      if (newDiscovery.lastSeen != -1000) //no new value from receivedValue() 
      { 
       UpdateTable(&discoveryTable, newDiscovery); 
      } 
      printTable(&discoveryTable); 
     } 
     return NULL; 
} 
+0

为什么你使用strcmp()和行进,而不是某种形式的关联容器?不必要地覆盖isNewEntry。 – 2010-02-01 18:32:23

+2

问题不在于您所显示的代码中,因此请显示更多代码,具体说明如何使用该功能。 – 2010-02-01 18:32:40

+4

你如何检查?我非常怀疑'push_back'正在无情地覆盖着某些东西。人们会告诉你,我会同意:使用C++! 'std :: string','std :: find'和更合适的容器都可以存储。 – GManNickG 2010-02-01 18:33:02

回答

3

我要大胆地猜测:

假设MyStruct声明如下

struct MyStruct 
{ 
    const char *sourceAddress; 
    // Other Gubbins ... 
}; 

ReceivedValue确实像

MyStruct ReceivedValue() 
{ 
    static char nameBuffer[MAX_NAME_LEN]; 

    // Do some work to get the value, put the name in the buffer 

    MyStruct s; 
    s.sourceAddress = nameBuffer; 
    // Fill out the rest of MyStruct 
    return s; 
} 

现在,每当你的结构推入你的矢量sourceAddress指向同一个glob al缓冲区,每次调用ReceivedValue时,它会用新字符串覆盖该缓冲区 - 因此,向量中的每个条目都以相同的字符串结尾。

我无法确定没有看到代码的其余部分,但我可以肯定的是,如果您在注释中遵循一些很好的C++风格建议,那么这种可能性将会消失。

编辑澄清:没有必要堆分配您的结构,只需将sourceAddress声明为std :: string就足以消除这种可能性。

+0

只需将它声明为一个char数组也可以修复它,并允许他保留现有的代码。 – 2010-02-01 19:38:31

+0

再看一遍,将“Sample”赋值给sourceAddress表明sourceAddress必须声明为const char *,而strcmp则不能是std :: string。只要“样本”没有被数组覆盖(我不认为我可以用这个答案解释),这将使这个问题成为该问题的候选人。 – 2010-02-01 21:27:16

0

你的代码对我来说看起来不错。有没有可能你没有通过正确的矢量?我的意思是,如果您在尝试添加第三个条目之前以某种方式将个人向量重置为其原始1进入状态,那么您所描述的行为将会出现,那么它会显示为您的第二个条目被覆盖。

这里是我的意思是:

int test_table() 
{ 
    string SampleAddresses[] = {"Sample Address 1", "Sample Address 2"}; 

    for (int i = 0; i < 2; i++) 
    { 
    // All this work to build the table *should* be done outside the loop; but we've accidentally put it inside 
    // So the 2nd time around we will destroy all the work we did the 1st time 
    vector<MyStruct> Individuals; 
    MyStruct Sample; 
    Sample.sourceAddress = "Sample Address 0"; 
    Test.push_back(Sample); 

    // this is all we meant to have in the loop 
    MyStruct NewEntry; 
    NewEntry.sourceAddress = SampleAddresses[i]; 
    UpdateTable(Individuals, NewEntry); 
    } 

    //Now the table has 2 entries - Sample Address 0 and Sample Address 2. 
} 

如果这是你所有的代码,那么问题将是显而易见的。但它可能隐藏在其他代码段中。

0

对我来说似乎很奇怪:也许//snip部分代码有问题吗?

尝试在push_back调用之前和之后(在调试器中或使用cout)记录矢量的大小,并查看isNewEntry变量。

+0

// snip部分没有任何重要性。然而,我附加了调用方法。 – Mark 2010-02-01 18:46:00

2

您推入数据库的项目的范围即将过期。当你离开其创建的{}时,它们被破坏 - 因此对它们的引用不再有效。

您需要将其从vector<MyStruct>更改为vector<MyStruct*>(最好使用来自Boost ::的安全指针而不是指针,但您明白了)。

您正在创建的(有限)范围内的项目,将其推到向量(而结构被复制,其中的字符串!)它,然后重复使用相同的存储位置(最有可能的如果进行了适当的优化)来存储下一个“新”结构和之后的结构等等等等。

取而代之,在限定的范围内创建MyStruct *myObject = new MyStruct并分配其值,然后将指针指向该向量。

请记住delete清除它之前的矢量的所有值/摧毁它!

或者,当然,您可以使用std :: string/CString/whatever来代替char数组,并通过具有安全复制结构来完全避免该问题。

+0

我花了一段时间才得到这个,所以这里有一条评论来澄清:你将地址存储为字符数组,这意味着结构实际知道的唯一事情就是数组的内存地址(即指向数组的指针) 。当循环来回时,数组已经超出了范围,所以指针(保存在向量中)无效。巧合的是,同一块内存被重新用于新结构的地址字段。所以旧指针再次变成巧合无效,这次指向新地址;这就是为什么IsNewEntry测试失败并且新结构没有被添加。 – 2010-02-01 18:56:22

+1

@计算机如果您将某个项目推入矢量中,则会进行复制。没有范围问题,如你所描述的。 – 2010-02-01 19:03:44

+0

但是,复制是一个char * - 不是整个字符数组。然后指针指向的数组超出了范围。 – 2010-02-01 19:04:57

1

ComputerGuru的答案在另一个选择中有效。你可以为MyStruct创建一个拷贝构造函数和重载操作符=。在这些操作中,您需要将实际字符串复制到新结构中。在C++中,结构只不过是具有默认公共访问权限的类,而不是默认的私有访问权限。另一种选择是使用std :: string而不是char *作为字符串值。 C++字符串已经有这种行为。

struct MyStruct { 
    std::string sourceAddress; 
    int lastSeen; 
    int beaconReceived; 
};