Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

reliable return pointer

Status
Not open for further replies.

butthead

Programmer
Feb 24, 2002
545
US
char *Strip (char *str)
{
const int x = strlen (str) + 1;
char *buff1 = new char [x];
char buff2 [25];
strcpy (buff1, str);

for (int y = 0; y < x; y++)
{
if (buff1 [y] != ',')
buff2 [y] = buff1 [y];
else
{
buff2 [y] = NULL;
break;
}
}

delete buff1;
return buff2;
}

is buff2 a reliable return pointer.
the code works but I seem to recall that
the memory space is not reliable for repeated
references to it by way of this pointer.
is it reliable for this usage.

Fields.push_back (Strip (a));

feel free to be harshly critical

tomcruz.net
 
It's not a reliable return value for any purpose.

It's a pointer to memory that was local to the [tt]Strip[/tt] function. When the [tt]Strip[/tt] function returns, that memory is available to be used for something else, and can be overwritten.

You should probably be using a string object of some sort, like [tt]std::string[/tt].
 
personally I think std::string id overrated, but I
use it on occasion.

I am assuming that you are saying that I would
be better off using a string object in this case,
not for the pointer but just because you feel that
a string object is better coding practice. I am just
in the habit of parsing my char arays. I sometimes
find this easier than trying to remember to many
functions and parameters that may or may not optimize
my code and in most cases do not make the binary any
smaller or larger.

I was pounding code a week ago late one night and the
next day I weant back to it and realized what it was
had just wrote. I had avoided this issue for years
because I had read in the books several years ago that
you dont do this. I dont get to much into the details
of why, I just write code. I just found it interesting
that it does work.

thanks you guys for all the help the last few years.
tek-tips has helped me improve my code skills in more
ways than one.

tomcruz.net
 
I am assuming that you are saying that I would
be better off using a string object in this case,
not for the pointer but just because you feel that
a string object is better coding practice.
Well, the string dynamically allocates the memory for you, then frees it when it goes out of scope. That means you won't be using invalid memory, and you won't need to free it manually.

So... the suggestion to use something like [tt]std::string[/tt] was as a direct solution to your problem However, I'd also consider it good coding practice in general.
 
you said it frees the memory when it goes out
of scope.

I dont see this as any better as far as using it as a return value so consequently is not adequate as a
solution. since by the time I am accessing the pointer
the memory space has already been deallocated and
I would not rely upon the pointer as 100%.

tomcruz.net
 
When you return an [tt]std::string[/tt] from a function, you get a copy of it in the calling function. That [tt]std::string[/tt] is not out of scope in the calling function.
 
so this is correct and acceptable

Fields.push_back (Strip (a).c_str ());

Code:
std::string Strip (char *str)
{
    const int x = strlen (str) + 1;
    char *buff1 = new char [x];
    char buff2 [25];

    strcpy (buff1, str);
    std::string  stri;

    for (int y = 0; y < x; y++)
    {
        if (buff1 [y] != ',')
             buff2 [y] = buff1 [y];
        else
        {
            buff2 [y] = NULL;
            break;
        }
    }

    delete buff1;
    stri = buff2;

    return stri ;
}

tomcruz.net
 
In terms of the return value, yes, it's correct and acceptable.

You could also just return [tt]buff2[/tt] and let the compiler convert it into an [tt]std::string[/tt].


Also, I'm not sure why you're making a copy of your parameter [tt]str[/tt]. You don't modify it at all, so you might as well just use the original.
 
You could also just return buff2 and let the compiler convert it into an std::string."

now Im confused. are we not back were we started.

perhaps I should get more sleep. ;-)

the copy process was just a method to preserve the
"str" value while I test. I sometimes write a little
more code at first to get things to work and then go back and clean up.


tomcruz.net
 
"You could also just return buff2 and let the compiler convert it into an std::string."

now Im confused. are we not back were we started.
Nope.

Your last code sample does the following:
[ul][li]takes a [tt]char *[/tt] ([tt]buff2[/tt] "decayed" from an array into a pointer) and assigns it to an [tt]std::string[/tt] ([tt]stri[/tt]),[/li]
[li]copies an [tt]std::string[/tt] ([tt]stri[/tt]) to another [tt]std::string[/tt] (the value returned from the function)[/li][/ul]

I suggested that you do that in one step:
[ul][li]take a [tt]char *[/tt] ([tt]buff2[/tt] "decayed" from an array into a pointer) and use it to construct an [tt]std::string[/tt] (the value returned from the function)[/li][/ul]

This prevents your program from walking across the string, copying each character into new memory, then repeating the process for no apparent reason.
 
As an example:
Code:
std::string(char *str)
{
    char buf[20] = str;

    // Play with buf

    return buf;  // return std::string(buf);
}


the copy process was just a method to preserve the
"str" value while I test. I sometimes write a little
more code at first to get things to work and then go back and clean up.

Understood.
 
Oops; pretend the function in my example has a name. Maybe I need more sleep, too.
 
I am not even going to ask what is the
diff between returning a char array and
then getting a std::string and not a
pointer or char array. I will just be content
for the moment to know that this is a quite
useful methd and I foresee that I will use it
a lot in the future. I am content with the
compiler doing for me what I cant do myself.


thanks
tomcruz.net
 
I am not even going to ask...
You shouldn't have to. I already explained it in a comment in the above example.

It's similar to the following:
Code:
char foo()
{
    return 64;
}

The compiler automatically converts 64 from an int to a char. In this case, the conversion is built into the language.


Same thing with this:
Code:
std::string bar()
{
    return "bob";
}

The compiler automatically converts "bob" from a const char * to an std::string. In this case, the conversion is made possible because of the [tt]std::string::string(const char *)[/tt] constructor.

The exact same thing happens when you write
Code:
std::string str = "bob";
return str;
except that an extra copy needlessly gets made (unless the compiler is smart enough to optimize it out).
 
I dont remember reading about this several
years ago when I started. I just more or less
just started coding and learned the minimum to
get the job done. I sometimes wish I had the
time to get into the detail but the last 2 or
three years I havent had much time to study.

actually tek-tips has been a classroom for me.

thanks again for all your help.

tomcruz.net
 
personally I think std::string id overrated

IMHO, There is a major advantage to using strings, either std::strings or AnsiStrings, to character arrays. With strings, you won't have the buffer overruns that occur with arrays.

For example, there was a famous program a few years ago that was discovered to have a major problem when it received more characters than it was expecting. The program's problem came from the input character array. The character array was defined at a certain length. When a large number of characters was input, much larger than the input array was expecting, the "cracker" could gain control over the program. Simply put, the code looked like:
Code:
char Someinput[100]; // Nobody in their right mind would input more that 99 characters, right?
cin >> Someinput; // But what happens when someone input 1000 characters?

With strings, the input grows as characters are added. If the numbers of characters grow beyond the ability of memory to hold it, a simple catch statement will grab the exception and stop the intrusion.

James P. Cottingham
-----------------------------------------
I'm number 1,229!
I'm number 1,229!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top