LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 07-29-2005, 05:03 PM   #1
realos
Member
 
Registered: Jul 2002
Location: Germany
Distribution: Redhat 7.3, Debian 3.1, Knoppix 3.1, Ubuntu 6.10
Posts: 113

Rep: Reputation: 15
Really strange change of string values in C


Code:
1 const char *menue();
2 int main(){
3	const char * file_name="";
4	
5	file_name = menue();
6	printf("menue ...done\n");
7	accessfile("file_name");
8	}
9 const char * menue(){
10	char file[20]="";	
11	scanf("%s",file);
12	fflush(stdin);
13	return(file);
14	}
Compiler gives following warning: "warning: function returns address of local variable"

I could retrieve following information through debugging:
Content of the variable "file" at exit point (line 13) from functin menue: file = "myfilename\000\000\000\000"

file_name="myfilename" (at line 5)
file_name="\?p\205\004\210\" a very long number of uncommon characters (at line 6 right after printing "menue() ...done")


Isn't it strange that return value from function menue() seems to be fully okay and then suddenly change of values in file_name.

Am I missing something important? Any idea?
 
Old 07-29-2005, 05:25 PM   #2
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
Automatic, local variables are placed on the stack. When the function begins to execute, the stack size is increased to create room for local variables in that function. When the function returns the stack size is returned to its previous size.

This means that your char file[20]="" is not guaranteed to exist when menue() returns. It's possible for the program to work okay, but it might not. To get around this you can declare file as static (i.e. static char file[20];. static variables are not placed on the stack and are guaranteed by the C standard to exist for the life of the program.
 
Old 07-29-2005, 05:29 PM   #3
trevilli
LQ Newbie
 
Registered: Mar 2004
Location: San Francisco Bay Area
Distribution: W: CentOS H: Ubuntu
Posts: 10

Rep: Reputation: 0
You're returning a pointer from an array that was defined locally in your function, hence the warning. My guess would be that once you return from the function, the memory reserved for the 'file' array is no longer reserved, and it is being overwritten.
 
Old 07-29-2005, 05:36 PM   #4
deiussum
Member
 
Registered: Aug 2003
Location: Santa Clara, CA
Distribution: Slackware
Posts: 895

Rep: Reputation: 31
Don't return a pointer to memory allocated on the local function stack. Very bad practice. You'll end up with dangling pointers.

Declaring it static would help in this case, be be warned that if you do that, whenever it is changed by calling that function, everything that is using the pointer returned from previous calls to that function is going to change as well...

A better solution would be to do something like what strcat, strcpy etc. do... Pass the pointer to an array into the function as a parameter and allocate it externally... Or, malloc the memory within the function and make sure when you are done with it you free it.
 
Old 07-29-2005, 05:50 PM   #5
exvor
Senior Member
 
Registered: Jul 2004
Location: Phoenix, Arizona
Distribution: LFS-Version SVN-20091202, Arch 2009.08
Posts: 1,485

Rep: Reputation: 66
yea you declared a constant then you inilized it with no information.

const char * file_name="";



when you did this you created an array with no elements that is a constant or read only.

as for the rest of your code i dont understand it or there is missing information.
 
Old 07-30-2005, 07:07 PM   #6
SiliconBadger
Member
 
Registered: May 2002
Location: Houston
Distribution: Gentoo
Posts: 32

Rep: Reputation: 15
Quote:
1 const char *menue();
2 int main(){
3 const char * file_name="";
4
5 file_name = menue();
6 printf("menue ...done\n");
7 accessfile("file_name");
8 }
9 const char * menue(){
10 char file[20]="";
11 scanf("%s",file);
12 fflush(stdin);
13 return(file);
14 }
to:

1 void menue(const char*);
2 int main(){
3 const char file_name[256];
4
5 menue(file_name);
6 printf("menue ...done\n");
7 accessfile("file_name");
8 }
9 void menue(const char* file){
10
11 scanf("%s",file);
12 fflush(stdin);
13 return;
14 }
 
Old 07-31-2005, 11:14 AM   #7
eddiebaby1023
Member
 
Registered: May 2005
Posts: 378

Rep: Reputation: 33
Quote:
Originally posted by exvor
yea you declared a constant then you inilized it with no information.

const char * file_name="";



when you did this you created an array with no elements that is a constant or read only.

as for the rest of your code i dont understand it or there is missing information.
You don't understand the bit you think you did, either!
He's declared a const char pointer which he's initialised with the address of a string containing only a terminating null byte, not "no elements". His problem is that the array he's passing out is on the stack and will be overwritten by the next function call, as has been noted by others above.
 
Old 07-31-2005, 11:51 AM   #8
exvor
Senior Member
 
Registered: Jul 2004
Location: Phoenix, Arizona
Distribution: LFS-Version SVN-20091202, Arch 2009.08
Posts: 1,485

Rep: Reputation: 66
const char * file_name="";

Yea i got that later looking at it again. Im not just used to seeing them done in that way
normally i use

const char *file_name;
 
Old 07-31-2005, 03:53 PM   #9
eddiebaby1023
Member
 
Registered: May 2005
Posts: 378

Rep: Reputation: 33
Quote:
Originally posted by exvor
const char * file_name="";

Yea i got that later looking at it again. Im not just used to seeing them done in that way
normally i use

const char *file_name;
So do I, the initial assignment is redundant. I find I have to study other people's code at least three times to get the hang of what they're doing. My own code often takes even longer.
 
Old 08-05-2005, 08:11 AM   #10
realos
Member
 
Registered: Jul 2002
Location: Germany
Distribution: Redhat 7.3, Debian 3.1, Knoppix 3.1, Ubuntu 6.10
Posts: 113

Original Poster
Rep: Reputation: 15
As noted by other quite a few forum members, the string (char *file) was being destroyed after exiting the function menue().

I changed that variable to static and now it is working fine. SiliconBadger suggested another way of passing the string to menue() function and thus reading the name of the file into this string.

Well, I see this string passing is also done in other c library functions like char *fgets(char *s, ...). Do you think it is a better approach as compared to using static variables?

2. Question: Does it make sense to use const in this declaration of a string with 256 character length?
Code:
3 const char file_name[256];
(ref SiliconBadger suggestion)

3. Question: Exvor,Eddiebaby: Isn't initialization of variables a good practice? I mean why would you people not do the declaration combined with initialization?

Last edited by realos; 08-05-2005 at 11:03 AM.
 
Old 08-05-2005, 10:29 AM   #11
deiussum
Member
 
Registered: Aug 2003
Location: Santa Clara, CA
Distribution: Slackware
Posts: 895

Rep: Reputation: 31
If you'll read my post above, I tried to explain the dangers of using static variables... Maybe a quick little example is needed.

Code:
#include <iostream>

char* Blah(int i)
{
    static char szString[8];

    if (i == 0)
    {
        strcpy(szString, "Dude!");
    }
    else
    {
        strcpy(szString, "Sweet!");
    }

    return szString;
}

int main()
{
    char* szResult1 = Blah(0);

    std::cout << "Result1: " << szResult1 << std::endl;

    char* szResult2 = Blah(1);

    std::cout << "Result1: " << szResult1 << std::endl;
    std::cout << "Result2: " << szResult2 << std::endl;

    return 0;
}
Code:
Result1: Dude!
Result1: Sweet!
Result2: Sweet!
For question 2, the const there is making the array unchangable. It has nothing to do with it being a constant length. If you try to change any element of the array when it is const, the compiler will complain. In the above example, I don't think const is really what is wanted as it makes the string you are trying to return unchangable.

For question 3. Initialization is definitely a GOOD THING! If you don't initialize your variables they will be in an unknown state and if you use them before they are assigned a value, you never know what will happen. It is not redundant at all to initialize it. In the above case if you DON'T initialize it, you will be left with a garbage string. And a const garbage string that you can't change, at that.

As a side note, with pointers you can have 2 different const attributes. The data the pointer points to can be const as in:
Code:
char szString[256];
const char* s = szString;
strcpy(s, "This is illegal!");
Or the pointer itself can be const meaning the data it points to can be changed, but the address of the pointer cannot, as in:

Code:
char szString[256];
char szString2[256];
char * const s = szString;
strcpy(s, "This is legal");
s = szString2; // This is not
Or, you can have both of them const, meaning you can't change the address or the value:

Code:
const char * const s = "This is unchangable!";
You probably won't see const pointers too often. Const data is much more common.
 
Old 08-05-2005, 11:34 AM   #12
Matir
Moderator
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Ubuntu
Posts: 8,507

Rep: Reputation: 118Reputation: 118
Also, if you ever write a threaded program, static variables are a huge no-no. They are not, by any means, thread-safe. This is the primary reason those functions take a pointer.
 
Old 08-05-2005, 03:09 PM   #13
exvor
Senior Member
 
Registered: Jul 2004
Location: Phoenix, Arizona
Distribution: LFS-Version SVN-20091202, Arch 2009.08
Posts: 1,485

Rep: Reputation: 66
Quote:
3. Question: Exvor,Eddiebaby: Isn't initialization of variables a good practice? I mean why would you people not do the declaration combined with initialization?

well you see char *somestring;

is not a variable its a pointer. its actually not even an array its a pointer of type char

you dont need to intilize this because its a pointer

consider the following code


Code:
 

char *ptr_string;


ptr_string = (char*) malloc (BUFF); // this will make ptr_string point to the 
                                                       // memory that malloc allocated 

char *static_string = "Voodoo"; // this will make an array with the elments
                                                  //Voodoo and then point to the array with 
                                                  //*static_string 

// note the above cannot be changed thus you cannot change the elements.
so when you do char *ptr_string = ""; the compiler is just ignoreing the = "" in actuallity its just making
your code harder to read.


and just for more info i have never seen this sort of declaration of a pointer even in a book
from 1994.


NOTE: the example or information on the second one may not be entirely correct but this
is due to a lack of depth of my understanding on pointers. It is indeed something that i need
to get more info on.

Last edited by exvor; 08-05-2005 at 03:13 PM.
 
Old 08-05-2005, 03:24 PM   #14
deiussum
Member
 
Registered: Aug 2003
Location: Santa Clara, CA
Distribution: Slackware
Posts: 895

Rep: Reputation: 31
excvor, it's a good practice to initialize all values, including pointers. In the case of pointers, NULL is a good value to initialize them to. Just because you are going to be setting them immediately after they are declared doesn't mean it's still not a good practice to initialize them just like any other variable. If nothing else it is a good way to see if the value has been changed later on if you need to do any cleanup.

For example:

Code:
char* pString = NULL;

if (somethingIsTrue)
{
   pString = new char[256];
   // stuff
}

// stuff

if (pString) 
{
    delete [] pString;   
}
And the compiler does NOT ignore the initialization. If you DON'T initialize it, your pointer will be pointing to some unknown memory location. Otherwise known as a dangling pointer. If you initialize a char* to "" it will be initialized to a location that it stored the constant string "" in. If you initialize it to NULL the address will be 0.

And in the comment on your third line example... that actually doesn't create an array with those values stored in it. At least not at the point of execution. At compile time string constants are generally assigned a location in the object code and then the initialization there just gives the pointer the address to that location.

Note: My examples have been C++ and the thread was asking about C, but the same basic memory ideals apply to C.

Last edited by deiussum; 08-05-2005 at 03:30 PM.
 
Old 08-05-2005, 06:09 PM   #15
exvor
Senior Member
 
Registered: Jul 2004
Location: Phoenix, Arizona
Distribution: LFS-Version SVN-20091202, Arch 2009.08
Posts: 1,485

Rep: Reputation: 66
Quote:
And the compiler does NOT ignore the initialization. If you DON'T initialize it, your pointer will be pointing to some unknown memory location. Otherwise known as a dangling pointer. If you initialize a char* to "" it will be initialized to a location that it stored the constant string "" in. If you initialize it to NULL the address will be 0.


forgive my ignorance here but why would you not initilize a pointer?
if i was going to point it to something right away why take up the resources to allocate it to a empty constant string
just seams kinda silly. i understand dangling pointers but if you have them in the first place it would be better to fix
them rather then have them doing nothing and taking up resources.

Actualy re reading the question above and learning more about pointers and stack with functions i
understand what happend as well. as i mentioned before im still learning anyway i guess the discussion above has nothing to do with the question so we should just drop it

Last edited by exvor; 08-05-2005 at 06:25 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
change case of a string (TOUPPER) in shell script raees Linux - Software 3 05-03-2005 02:13 PM
MySQL Returning very strange Values in PHP Script benrose111488 Programming 2 10-21-2004 11:26 AM
Strange string in log file ne21 Linux - Security 2 04-18-2004 04:23 AM
How to change parameter values of a function in shell script? Bassam Programming 0 01-25-2004 09:52 AM
Change prompt values from within a C++ program pshea Linux - Newbie 0 09-16-2003 11:06 PM


All times are GMT -5. The time now is 07:29 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration