Problems with new and scope

Started by
16 comments, last by Orpheum 23 years, 9 months ago
Heres a rather perplexing one... I have an object which contains many char* variables, which are ''new''ed in the initialize() function when variable strings are read in from a file. Stepping through the function in the debugger, I can see that the memory is being allocated and that the strings are being copied from the file into my new buffers. The problem is, once the flow of execution leaves the scope of that function, the variables are gone! When the flow is in main(), I test for a.fre_prefix and it says "CXX0030: Error: Expression cannot be evaluated". When the flow has entered the next function, testing for fre_prefix has the same result. I have no idea why this is happening... when in initialize(), the ''this'' tab of the debugger watch window has everything filled in, but once you step out of the function... blammo! Everything is gone. It is almost like the initialize function is using its own object with function scope! initialize() has no parameters, and no objects are declared in the function. The variables are defined like so in the private section of the object: char* chk_prefix; char* fre_prefix; char* chk_wks_suffix; char* chk_srv_suffix; char* fre_wks_suffix; char* fre_srv_suffix; Then in initialize(), they are allocated this way: if(stricmp(szVariable, "PathToFreBuilds") == 0) { fre_prefix = new char[strlen(szData) + 1]; strcpy(fre_prefix, szData); } else if(stricmp(szVariable, "PathToChkBuilds") == 0) { chk_prefix = new char[strlen(szData) + 1]; strcpy(chk_prefix, szData); } else if(stricmp(szVariable, "SuffixForFreWks") == 0) { fre_wks_suffix = new char[strlen(szData) + 1]; strcpy(fre_wks_suffix, szData); } etc etc... I think I''ve put enough info up here to be helpful... if you guys need anymore, just ask.... I''m anxious to move beyond this problem so I will be checking the boards regularly. Thanks!!
There is no spoon.
Advertisement
OK. I remember my prof going over this exact thing in class a few semesters ago so let''s see how much I remember.

I think, and a confirmation from someone else would be nice, that when you use the new operator, the scope of that variable is only within the current function and any functions you pass it to. So when you leave the function, the char* cannot be seen. They still exist just aren''t in scope. Hope thats right and hope that helps. and I am 99% sure thats right, but someone else saying so would be great.
Well, it really has nothing to do with the new operator. The problem is that fre_prefix is declared in the PRIVATE section of the class. This means that the variable is visible ONLY inside class methods, even to the debugger. It still exists in memory, you just can''t access it.

It''s a completely different issue about the "this" pointer, though. The reason you can''t look at it after the function returns is because it only exists INSIDE the function. The data it points to still exists in memory somewhere, but the actual variable named "this" exists only within the scope of the method. Think of it this way: When you call the function, the variable "this" is created on THE STACK. When you return from that function the stack frame is now completely different and the "this" variable ceases to exist.

Hmm... well every function used in the program is a method of the same class, so you would think that when the flow enters another of the class''s functions, you could see the variables. So if really is limited to scope, how would you suggest that I allocate these char*''s so that they stay there and can be used later in the program? I have done this many times before, and have had no problems... I have no idea what is different this time.
There is no spoon.
Both of the previous responders are incorrect. You can view private member variables with the debugger (you just have to have an object obj->m_private, or just m_private if you''re in a class function). New''d variables DO NOT leave scope. The only thing that ever leaves scope are things that are declared within that scope (including parameters). Things that are new''d must be delete''d explicitly--there''s no automatic deallocation. The pointer that points to that memory may go away if it was declared in scope, but the memory is still allocated (that''s what happens when memory leaks).

I suspect something else is going wrong here; maybe your pointers are being overwritten by something else? Look at the variable that gives you the problem, note the address that''s returned by new and make sure that variable has the same address when it''s used.

Also, maybe something somewhere is deleting this associated memory? I used to be in the habit of assigning a pointer to NULL every time I deleted its contents, and it''s a good habit to have (I''ve unfortunately grown out of it). This way you can tell if you get to the function and the pointer = NULL that it''s been deleted.

Just make sure that the pointer is in fact the problem. It looks from your description like you''re doing the right thing.

BTW, it should go without saying that these member variables should all be initialized to NULL in the constructor to show that no memory has been allocated to them yet. But there, I just said it anyway.

P.S.: why do people respond with incorrect information? Either you''re sure you know something that''s false (in which case I pity you), or you''re not sure what you''re talking about and you feel like responding anyway. Please, don''t.
quote:Original post by Stoffel

P.S.: why do people respond with incorrect information? Either you''re sure you know something that''s false (in which case I pity you), or you''re not sure what you''re talking about and you feel like responding anyway. Please, don''t.


I think that sometimes, people aren''t 100% sure, but they like to be as helpful as possible. For example, dbrooking flat out said that he wasn''t sure about what he was saying. Nothing wrong with that. The reader just needs to take it with a grain of salt.

Anyway... as far as your problem, Orpheum, if you haven''t figured it out yet, why don''t you post some more of your code to the initialize function (or all of it, if that is practical). Or maybe you could post the section of code where it is getting used? It is possible that you are somehow ending up with a different instance of your class that hasn''t been initialized? Of the top of my head, I can''t think of an instance where that could happen on accident, but who knows?

Thanks for your help so far guys... we will get to the bottom of this Im sure. Because this is such a fucked up problem, I will post all of my class header, initialize function, and my main function so everyone can see what I''m doing.

**installer.h**

#ifndef installer_h
#define installer_h


#include
#include
#include
#include
#include
#include
#include

#include "file_parser.h"


class installer
{
public:
installer();
~installer();

bool initialize(); //reads in settings from user.ini
void input_build(); //display and get build #
void input_version(); //display and get version type
void input_drive(); //display and get target drive
void finish(); //clean up temp files, start install

/*****Utility Functions*****/

void format(int* drives, int count); //format drive menu/function
void output_file(char* build, char* mach_name); //output answer file
void parse(int sel); //parse a file
void reset_loop();
void title(void); //display the banner

private:
/*****Path Strings*****/

char path_buffer[_MAX_PATH];

char* chk_prefix;
char* fre_prefix;
char* chk_wks_suffix;
char* chk_srv_suffix;
char* fre_wks_suffix;
char* fre_srv_suffix;
char* temp_drive_path;
char* unattend_path;

/******User Variables*****/

char build[5];
bool chk; //chk or fre
char drive; //what drive to install on to
char* domain; //the domain to be joined
char* user; //user name for domain
char* pass; //password for domain
char* mach_name; //get the machine name
bool more_loop; //loop control
char os; //wks ''P'', srv ''S''
};

#endif


**installer::initialize()**

bool installer::initialize()
{
char szBuffer[BUFSIZ];
char szVariable[64];
char szData[256];
int i = 0,
j = 0;

/******Clean Buffers******/

for(i = 0; i <= BUFSIZ; i++)
szBuffer = ''\0'';

for(i = 0; i < 65; i++)
szVariable = ''\0'';<br><br>for(i = 0; i < 257; i++)<br> szData = ''\0'';<br><br>i = 0;<br> <br> <br>//read in .ini file<br><br>ifstream in("Installer.ini", ios::nocreate);<br><br>if(!in)<br>{<br> cerr << endl << endl << "Installer.ini not found! Verify the file exists and is in the root directory." << endl << endl;<br><br> return false;<br>}<br><br>while(in.getline(szBuffer, BUFSIZ, ''\n''))<br>{<br> if((szBuffer[0] != ''['') && (szBuffer[0] != '' '') && (szBuffer[0] != ''\0'') && (szBuffer[0] != ''/''))<br> {<br> while(szBuffer != '' '')<br> {<br> szVariable = szBuffer;<br> i++;<br> }<br><br> i += 3; //move i to the other side of " = "<br><br> while(szBuffer != ''\0'' && szBuffer != '' '')<br> {<br> szData[j] = szBuffer;<br> i++;<br> j++;<br> }<br> <br> //all these are ok when flow in inside initialize()<br> if(stricmp(szVariable, "PathToFreBuilds") == 0)<br> {<br> fre_prefix = new char[strlen(szData) + 1];<br> strcpy(fre_prefix, szData);<br> }<br> else if(stricmp(szVariable, "PathToChkBuilds") == 0)<br> {<br> chk_prefix = new char[strlen(szData) + 1];<br> strcpy(chk_prefix, szData);<br> }<br> else if(stricmp(szVariable, "SuffixForFreWks") == 0)<br> {<br> fre_wks_suffix = new char[strlen(szData) + 1];<br> strcpy(fre_wks_suffix, szData);<br> }<br> else if(stricmp(szVariable, "SuffixForFreSrv") == 0)<br> {<br> fre_srv_suffix = new char[strlen(szData) + 1];<br> strcpy(fre_srv_suffix, szData);<br> }<br> else if(stricmp(szVariable, "SuffixForChkWks") == 0)<br> {<br> chk_wks_suffix = new char[strlen(szData) + 1];<br> strcpy(chk_wks_suffix, szData);<br> }<br> else if(stricmp(szVariable, "SuffixForChkSrv") == 0)<br> {<br> chk_srv_suffix = new char[strlen(szData) + 1]; strcpy(chk_srv_suffix, szData);<br> }<br> else if(stricmp(szVariable, "Domain") == 0)<br> {<br> domain = new char[strlen(szData) + 1];<br> strcpy(domain, szData);<br> }<br> else if(stricmp(szVariable, "User") == 0)<br> {<br> user = new char[strlen(szData) + 1];<br> strcpy(user, szData);<br> }<br> else if(stricmp(szVariable, "Pass") == 0)<br> {<br> pass = new char[strlen(szData) + 1];<br> strcpy(pass, szData);<br> }<br> <br> /******Clean Buffers******/<br><br> for(i = 0; i <= BUFSIZ; i++)<br> szBuffer = ''\0'';<br> <br> for(i = 0; i < 65; i++)<br> szVariable = ''\0'';<br><br> for(i = 0; i < 257; i++)<br> szData = ''\0'';<br><br> i = 0;<br> j = 0;<br> }<br> }<br> <br> in.close();<br><br> return true;<br>}<br><br><br>**main()**<br><br>#include "installer.h"<br><br>int main()<br>{<br> installer a;<br> <br>/* <br> if(a.initialize() == false) //wtf is wrong here!?!?<br> exit(1);<br>*/<br> a.initialize(); //as soon as the flow leaves here, poof!<br> a.title(); //a.fre_wks says nothing!!<br><br> a.input_build();<br> a.reset_loop();<br> a.input_version();<br> a.reset_loop();<br> a.input_drive();<br><br> a.finish();<br><br> return 0;<br>}<br> </i>
There is no spoon.
top tip, when posting code, put it in the [ / source ] and [ / source ] tags, minus the spaces, naturally
at least then we can read it

Nick - Head Designer, Llamasoft.net

--
Visit our website...

Llamasoft.net
Games, goodies and ingenuity

Edited by - Llamasoft.net on July 21, 2000 7:43:49 PM
Nick - Head Designer, Llamasoft.net--Visit our website...Llamasoft.netGames, goodies and ingenuity
/source

cout << "testing, testing...";

/source
There is no spoon.
[/source]

cout << "testing, testing...";

[/source]
There is no spoon.

This topic is closed to new replies.

Advertisement