Jump to content
  • Advertisement
Sign in to follow this  
choffstein

std::vector push_back and size issues *FIXED*

This topic is 4956 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have recently been doing some coding and come across a very, very wierd bug which is impossible for me to duplicate. For the sheer sake of making things easier to diagnose for everyone, I wrote up this pseudo code:
#include <iostream>
#include <vector>
using namespace std;

class BaseClass{
   public:
       int value;  
       BaseClass(){ value = 0; }
};

class MajorClass{
   public:
       int numBaseClasses;
       std::vector<BaseClass> BaseClasses;
       MajorClass(){ numBaseClasses = 0; BaseClasses.clear(); }
       ~MajorClass(){ BaseClasses.clear(); }    
       int addClass();
};

int MajorClass::addClass(void){
    cout << "Size of Major Class at top of add: " << BaseClasses.size() << endl;
    BaseClass temp;
    temp.value = ++numBaseClasses;
    BaseClasses.push_back(temp);
    cout << "Size of Major Class after adding " << numBaseClasses << " classes: " << BaseClasses.size() << endl;
    return 1;
}   

MajorClass mc;

int changeValue(BaseClass *bc, int value){
       bc->value = value;
       return 1;
}     

int main(){
   mc.addClass();
   cout << "Size of Major Class after returning from add: " << mc.BaseClasses.size() << endl;
   mc.addClass();    
   cout << "Size of Major Class after returning from add: " << mc.BaseClasses.size() << endl;
   
   cout << mc.BaseClasses[0].value << endl;
   cout << mc.BaseClasses[1].value << endl;
   
   changeValue(&mc.BaseClasses[0], 5);
   cout << mc.BaseClasses[0].value << endl;
   
   system("PAUSE");
   return 1;
}    



Essentially, you have a base class and a major class which contains a vector of base classes. Essentially, this is what I am doing in my code. The output of this is:
Size of Major Class at top of add: 0
Size of Major Class after adding 1 classes: 1
Size of Major Class after returning from add: 1
Size of Major Class at top of add: 1
Size of Major Class after adding 2 classes: 2
Size of Major Class after returning from add: 2
1
2
5


The issue is, however, (and for some reason, its not in this code when you compile it...) that within my equivalent "addClass()" function, everytime I push I get size "1" or size "2", as it should be. However, outside the class function, in my main method, I am getting size "1539705258" and "3079410516"...every single time. But once I get back into the class method, I get 1 and 2 again, despite the fact I call size() almost back to back. I litterally call it one way (BaseClasses.size()), return to my main function, and call it again (as mc.BaseClasses.size()) and get something different. Does anyone have any idea what is going on? I have tried to isolate what is going on, calling things both in and outside the function. My actual code always crashses on this line:
cout << "Script Name 2: " << vm.scripts[1].szName << endl;    


The line is basically the mc.BaseClasses[1].value equivalent line. Anyone have any ideas, or how to get more info on this? I have tried to gather as much as I could, but am at a complete loss. All the data in the base class loads correctly, and everything seems to be fine within the class method...but once I try to call it outside the class method, the program crashes (memory issue, I would assume). The output from my program I am getting is:
Size of Scripts before anything: 0
Size of scripts at top of add: 0
Size of scripts after push back: 1
Script name (in class method): thread1.vse
Size of Scripts after add (in main method): 1539705258
Size of scripts at top of add: 1
Size of scripts after push back: 2
Script name (in class method): thread2.vse
Size of Scripts after add (in main method): 3079410516
Script Name 1 (in main method): thread1.vse
Script Name 2 (in main method): 


It crashses when trying to access the name of the second script Thanks for taking the time to read this. -visage [Edited by - visage on November 28, 2004 6:05:35 PM]

Share this post


Link to post
Share on other sites
Advertisement
My magic 8-balls says : "Reference or pointer to a local variable".

I don't understand why you decided to show us code that does not trigger the error. Is it some kind of augury technique where we are supposed to find your errors by examining the entrails of a sacrificial program (cyber-haruspicy?)

I've seen the word 'thread'. Are you protecting your containers from race conditions?

Share this post


Link to post
Share on other sites
Sorry. The code that does trigger the error is much, much longer. About ...3000 lines longer :D I was trying to recreate the error and simply cant...except it seems to continue to exist in my other code.

Ignore anything about threads. Its for my scripting language, and im trying to get several scripts running at once...hence why I call them thread1 and thread2. Has nothing to do with race conditions. A good thought though.


Below is the actual code:


/*

WITHIN MY MAIN METHOD

*/


voodoomachine vm;

cout << "Size of Scripts before anything: " << vm.scripts.size() << endl;
r = vm.loadScript("thread1.vse");
cout << "Size of Scripts after add (in main method): " << vm.scripts.size() << endl;
if(r < 0){
cout << "Could not load script \"thread1.vse\"." << endl;
}
r = vm.loadScript("thread2.vse");
cout << "Size of Scripts after add (in main method): " << vm.scripts.size() << endl;
if(r < 0){
cout << "Could not load script \"thread2.vse\"." << endl;
}

cout << "Script Name 1: " << vm.scripts[0].szName << endl;
cout << "Script Name 2: " << vm.scripts[1].szName << endl;





/*

LOADSCRIPT method

*/

int voodoomachine::loadScript(std::string filename){
FILE *fp;
voodooscript tempScript;
std::string tempChar;
int instrStreamSize;

cout << "Size of scripts at top of add: " << scripts.size() << endl;

fp = fopen(filename.c_str(), "rb");
if(fp == NULL){
return FILE_DOES_NOT_EXIST;
}

//the file is open
tempScript.szName = filename;
for(int i = 0; i < 5; i++){
tempChar += fgetc(fp);
}
tempChar += '\0';
if(strcmp(tempChar.c_str(), CURR_VER)) return INCORRECT_VERSION;
tempChar.clear();

fread(&tempScript.header.iStackSize, sizeof(int), 1, fp);
if(tempScript.header.iStackSize == 0) tempScript.header.iStackSize = 1024;
tempScript.stack = (Op*)malloc(sizeof(Op)*tempScript.header.iStackSize);
if(tempScript.stack == NULL)
return -1;
for(int i = 0; i < tempScript.header.iStackSize; i++){
tempScript.stack.iType = 0;
tempScript.stack.iIntLiteral = 0;
}
fread(&tempScript.header.iGlobalDataSize, sizeof(int), 1, fp);
fread(&tempScript.header.iIsMainFunction, sizeof(int), 1, fp);
fread(&tempScript.header.iMainFunctionIndex, sizeof(int), 1, fp);
fread(&tempScript.header.iPriority, sizeof(int), 1, fp);
fread(&tempScript.header.iIsConstruct, sizeof(int), 1, fp);
fread(&tempScript.header.iConstructIndex, sizeof(int), 1, fp);
fread(&tempScript.header.iIsDeconstruct, sizeof(int), 1, fp);
fread(&tempScript.header.iDeconstructIndex, sizeof(int), 1, fp);

fread(&tempScript.iNumLines, sizeof(int), 1, fp);

tempScript.loadOps(fp, tempScript.iNumLines);
cout << "Size of scripts after loadops: " << scripts.size() << endl;

int numFuncs;
fread(&numFuncs, sizeof(int), 1, fp);
for(int i = 0; i < numFuncs; i++){
tempChar.clear();
function temp;
int nameSize;
fread(&temp.iIndex, sizeof(int), 1, fp);
fread(&nameSize, sizeof(int), 1, fp);
for(int i = 0; i < nameSize; i++){
tempChar += fgetc(fp);
}
temp.szName = tempChar;
fread(&temp.iEntryPoint, sizeof(int), 1, fp);
fread(&temp.iParamCount, sizeof(int), 1, fp);
fread(&temp.iLocalDataSize, sizeof(int), 1, fp);
tempScript.funcTable.push_back(temp);
}

int numObjects;
fread(&numObjects, sizeof(int), 1, fp);
for(int i = 0; i < numObjects; i++){
tempChar.clear();
object temp;
int nameSize;
fread(&temp.iIndex, sizeof(int), 1, fp);
fread(&nameSize, sizeof(int), 1, fp);
for(int i = 0; i < nameSize; i++){
tempChar += fgetc(fp);
}
temp.szName = tempChar;
fread(&temp.iSize, sizeof(int), 1, fp);
fread(&temp.iStackIndex, sizeof(int), 1, fp);
fread(&temp.iFuncIndex, sizeof(int), 1, fp);
tempScript.objectTable.push_back(temp);
}

int numStrings;
fread(&numStrings, sizeof(int), 1, fp);
for(int i = 0; i < numStrings; i++){
tempChar.clear();
int nameSize;
fread(&nameSize, sizeof(int), 1, fp);
for(int i = 0; i < nameSize; i++){
tempChar += fgetc(fp);
}
tempScript.stringTable.push_back(tempChar);
}

int numLabels;
fread(&numLabels, sizeof(int), 1, fp);
for(int i = 0; i < numLabels; i++){
tempChar.clear();
label temp;
int nameSize;
fread(&temp.iIndex, sizeof(int), 1, fp);
fread(&nameSize, sizeof(int), 1, fp);
for(int i = 0; i < nameSize; i++){
tempChar += fgetc(fp);
}
temp.szName = tempChar;
fread(&temp.iTargetIndex, sizeof(int), 1, fp);
fread(&temp.iFuncIndex, sizeof(int), 1, fp);
tempScript.labelTable.push_back(temp);
}

tempScript.iScriptNum = scriptNum++;

if(fgetc(fp) != EOF)
return LAST_MINUTE_READ_ERROR;

fclose(fp);

if(tempScript.header.iIsMainFunction == 1){
//the current line should be the iEntry point of the function located at
//the iMainFunctionIndex

//PushFrame(&tempScript, tempScript.funcTable[tempScript.header.iMainFunctionIndex].iLocalDataSize);
tempScript.iCurLine = tempScript.funcTable[tempScript.header.iMainFunctionIndex].iEntryPoint;
tempScript.iIsDone = 0;
}
else{
tempScript.iIsDone = 1;
}

//push it onto our scripts
scripts.push_back(tempScript);
cout << "Size of scripts after pushback: " << scripts.size() << endl;
cout << "Script name (in class method): " << scripts[scriptNum-1].szName << endl;
return 1;
}



Thanks for looking!

Share this post


Link to post
Share on other sites
Can you show me the class declaration? I'm especially interested in the variable that is located right before scripts in the structure.

Share this post


Link to post
Share on other sites
Here you go!


class voodoomachine {
public:
voodoomachine(){ scriptNum = 0; currScript = 0; }
~voodoomachine(){}

int scriptNum; //number of scripts
int currScript; //the current script we are processing
std::vector<voodooscript> scripts; //the scripts themselves

//prototypes
...
};



Thanks for looking!

Share this post


Link to post
Share on other sites
Nope, I can't think of a solution... though I noticed that your 'size after loadOps' never appeared in the output.

Share this post


Link to post
Share on other sites
Yeah, its because I removed it from the original post...it does actually appear in my output.

Everything prints...just comes up with some wacky stuff.

Share this post


Link to post
Share on other sites
Quote:
Original post by visage
Yeah, its because I removed it from the original post...it does actually appear in my output.

Everything prints...just comes up with some wacky stuff.


Well, add some more until you do find the point where the data structure goes bonkers. If it happens during the function returns, you'll have to trace it in the debugger...

Share this post


Link to post
Share on other sites
Thanks for the help Fruny. I just ended up making my vector a bunch of pointers instead of copies of the classes. I think it had something to do with my deconstructor...though honestly, I dont know. It works now...

Thanks again

Share this post


Link to post
Share on other sites
Show us the copy constructor and destructor of voodooscript, or better yet the whole class if it's not too large. I doubt the problem is really solved yet, you just pushed it away for a while. Since voodooscript has dynamically allocated members, it'd better also have those two well implemented (well, assignment operator too but that isn't called here).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!