472,954 Members | 1,589 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,954 software developers and data experts.

pass char * as reference and reallocate memory for a pointer

Hi,
basically, the test function get a char pointer, and assigned a string
to it. then the string is passed back by the call-by-reference
mechanism. in test(), I reallocate some memory for the pointer, the
size is not fixed.

I remember, all new statement should be followed by a delete statement,

is there some memory leak here?
void test(char* &str)
{
// don't know how long the string might be
char *astring = "a string to return after thinking, not
fixed length";
str = new char[strlen(astring)+1];

strcpy(str, astring );
cout<<"test "<<str<<endl;

}
void main(void)
{
char *astr = "";

test(astr);
cout<<astr<<endl;
}

Dec 14 '06 #1
18 9007

happyvalley wrote:
Hi,
basically, the test function get a char pointer, and assigned a string
to it. then the string is passed back by the call-by-reference
mechanism. in test(), I reallocate some memory for the pointer, the
size is not fixed.

I remember, all new statement should be followed by a delete statement,

is there some memory leak here?
void test(char* &str)
{
// don't know how long the string might be
char *astring = "a string to return after thinking, not
fixed length";
str = new char[strlen(astring)+1];

strcpy(str, astring );
cout<<"test "<<str<<endl;

}
void main(void)
{
char *astr = "";

test(astr);
cout<<astr<<endl;
}
Yes, thats a leak. Whats wrong with the string class? It has a member
function c_str() which returns a const ptr to char.

#include <iostream>
#include <ostream>
#include <string>

void test(std::string& r_s)
{
r_s += "a string to return after thinking";
}

int main()
{
std::string s;
test(s);
std::cout << s << std::endl;
}

/*
a string to return after thinking
*/

Dec 14 '06 #2

Salt_Peter wrote:
happyvalley wrote:
Hi,
basically, the test function get a char pointer, and assigned a string
to it. then the string is passed back by the call-by-reference
mechanism. in test(), I reallocate some memory for the pointer, the
size is not fixed.

I remember, all new statement should be followed by a delete statement,

is there some memory leak here?
void test(char* &str)
{
// don't know how long the string might be
char *astring = "a string to return after thinking, not
fixed length";
str = new char[strlen(astring)+1];

strcpy(str, astring );
cout<<"test "<<str<<endl;

}
void main(void)
{
char *astr = "";

test(astr);
cout<<astr<<endl;
}

Yes, thats a leak. Whats wrong with the string class? It has a member
function c_str() which returns a const ptr to char.

#include <iostream>
#include <ostream>
#include <string>

void test(std::string& r_s)
{
r_s += "a string to return after thinking";
}

int main()
{
std::string s;
test(s);
std::cout << s << std::endl;
}

/*
a string to return after thinking
*/
thanks for your reply, yes string works, just want to make it straight.
the main() passes a pointer to the test(), while the new statement
only allocate some memory for the pointer, not create a new pointer,
right. after return to the main(), the pointer will die when go out of
scope. right?
I put delete astr at the end of main(), no error.
how can I check if there is a memory leak?
thanks again

Dec 14 '06 #3
>
void main(void)
{
char *astr = "";

test(astr);
cout<<astr<<endl;
}
I see that when the function test is called the pointer is passed by
value, you are just passing the address that the pointer is pointing to
and any change of the pointer in the function will not reflect outside
and hence it is a memory leak...

Hope it helps...

Dec 14 '06 #4

sam_...@yahoo.co.in wrote:

void main(void)
{
char *astr = "";

test(astr);
cout<<astr<<endl;
}

I see that when the function test is called the pointer is passed by
value, you are just passing the address that the pointer is pointing to
and any change of the pointer in the function will not reflect outside
and hence it is a memory leak...

Hope it helps...
you mean, test(char * &str) is call by value, if so, how to pass the
char pointer by reference? thanks, get confused.

void test(char* &str)
{
char *astring = "a string to return after thinking";
str = new char[strlen(astring)+1];
strcpy(str, astring );
}

Dec 14 '06 #5
>
you mean, test(char * &str) is call by value, if so, how to pass the
char pointer by reference? thanks, get confused.

void test(char* &str)
{
char *astring = "a string to return after thinking";
str = new char[strlen(astring)+1];
strcpy(str, astring );
}
Pass the pointer by reference, pass the address of the pointer

test(&p_str)

void(char** p_p_str)
{
}

Hope it helps...

Dec 14 '06 #6

sa*****@yahoo.co.in wrote:

void main(void)
{
char *astr = "";

test(astr);
cout<<astr<<endl;
}

I see that when the function test is called the pointer is passed by
value, you are just passing the address that the pointer is pointing to
and any change of the pointer in the function will not reflect outside
and hence it is a memory leak...
No, it's passed by reference; see the definition of the test()
function.
>From what I can see the "leak" is caused by the fact that there is no
"delete astr" at the end of main. It isn't technically a leak though
because a leak is a reoccuring allocation of memory that isn't deleted.
This one can't reoccur.

There's plenty of potential for problems in the OP's code though. It
is _extreemly_ tough to make safe char* functions. You will always
have to rely on developer vigilance to keep bugs out of the code when
dealing with char*. Such functions are very fragile in the face of
change. In comparison to std::string it just plain isn't worth the
trouble.

Dec 14 '06 #7

happyvalley wrote:
Salt_Peter wrote:
happyvalley wrote:
Hi,
basically, the test function get a char pointer, and assigned a string
to it. then the string is passed back by the call-by-reference
mechanism. in test(), I reallocate some memory for the pointer, the
size is not fixed.
>
I remember, all new statement should be followed by a delete statement,
>
is there some memory leak here?
>
>
void test(char* &str)
{
// don't know how long the string might be
char *astring = "a string to return after thinking, not
fixed length";
str = new char[strlen(astring)+1];
>
strcpy(str, astring );
cout<<"test "<<str<<endl;
>
}
>
>
void main(void)
{
char *astr = "";
>
test(astr);
cout<<astr<<endl;
}
Yes, thats a leak. Whats wrong with the string class? It has a member
function c_str() which returns a const ptr to char.

#include <iostream>
#include <ostream>
#include <string>

void test(std::string& r_s)
{
r_s += "a string to return after thinking";
}

int main()
{
std::string s;
test(s);
std::cout << s << std::endl;
}

/*
a string to return after thinking
*/

thanks for your reply, yes string works, just want to make it straight.
the main() passes a pointer to the test(), while the new statement
only allocate some memory for the pointer, not create a new pointer,
right. after return to the main(), the pointer will die when go out of
scope. right?
I put delete astr at the end of main(), no error.
how can I check if there is a memory leak?
thanks again
No, std::string s is an object with its own lifetime. It is passed by
reference to test(...). The program exhibits no leaks whatsoever. A
reference is akin to a const_pointer on steroids that can't be
reseated. You could do the same with a const pointer:

void test(std::string* const p_s)
{
*p_s += "a string to return after thinking";
// p_s = new std::string("another string"); // error, not allowed
}

Like a const pointer, a reference is not allowed to refer to another
object.
Thats safety built in to the design, the const keyword is critical. If
you take the discussion one step further: a const reference is
non-mutable _and_ not reseatable. So if wanted a function to display
the std::string and guarentee that the std::string cannot be modified
by anybody:

void display(const std::string& r_s) // by const ref
{
std::cout << r_s << std::endl;
}

display(...) is not allowed to change that string. It can only read it.
Its equivalent in pointer-speak:

void display(const std::string* const p_s) // by const ptr to const s
{
std::cout << *p_s << std::endl;
}

I'ld suggest writing code without new/delete. You'll find that such
code is much easier to write and maintain.

Dec 14 '06 #8

Salt_Peter wrote:
I'ld suggest writing code without new/delete. You'll find that such
code is much easier to write and maintain.
Hmm very strange recommendation. I would hardly imagine any nontrivial
C++ application, that does not use objects from the heap.

Dec 14 '06 #9

Vyacheslav Kononenko wrote:
Salt_Peter wrote:
I'ld suggest writing code without new/delete. You'll find that such
code is much easier to write and maintain.

Hmm very strange recommendation. I would hardly imagine any nontrivial
C++ application, that does not use objects from the heap.
True, but it can still be avoided. For example in this case. If you
use std::string there is no need to use new/delete yourself. Rely on
the standard library and language mechanics to do it for you.

Dec 14 '06 #10

Noah Roberts wrote:
No, it's passed by reference; see the definition of the test()
function.
correct, this part will work
From what I can see the "leak" is caused by the fact that there is no
"delete astr" at the end of main.
you need delete [] astr
to deallocate an array of allocated memory

--
Ivan
htttp://www.0x4849.net

Dec 14 '06 #11

happyvalley wrote:
is there some memory leak here?
Run valgrind with --leak-check=full on your program that will give the
answer. www.valgrind.org.

--
Ivan
http://www.0x4849.net

Dec 14 '06 #12
Noah Roberts wrote:
True, but it can still be avoided. For example in this case. If you
use std::string there is no need to use new/delete yourself. Rely on
the standard library and language mechanics to do it for you.
Yes it can and usually it should. But I have an impression that this
case is just a simplified test of concept on how a function can return
a dynamically allocated object. So that recommendation could be
understood as generic by the author.

Dec 14 '06 #13

sa*****@yahoo.co.in wrote:
Pass the pointer by reference
That's exactly what the OP did.

void test(char* &p_str);

is not passing by value.
pass the address of the pointer
Not necessary.
test(&p_str)

void(char** p_p_str)
{
}
That's worse than what the OP had. If someone is having difficulty with
pointers and memory management, adding an extra level of indirection
won't help understanding. Moreover, the OP's passing by reference was
equivalent to passing a const pointer to a char*. You've thrown away
that const.

Gavin Deane

Dec 14 '06 #14

Vyacheslav Kononenko wrote:
Salt_Peter wrote:
I'ld suggest writing code without new/delete. You'll find that such
code is much easier to write and maintain.

Hmm very strange recommendation. I would hardly imagine any nontrivial
C++ application, that does not use objects from the heap.
Who said not to use the heap? Since when do you require new/delete for
the heap? Entire applications can be written, and are written, without
a single delete - and those applications are rock solid.
Whats stopping you from using a smart_pointer like std::auto_ptr,
boost::shared_ptr or boost::shared_array, etc? Why not let a std
container provide RAII for you? Even in the case where you must
allocate elements, why deal with the headaches of deallocation when you
can do as follows:

#include <deque>
#include <boost/shared_ptr.hpp>

class A { ];
int main()
{
typedef boost::shared_ptr< A SPtr_A;
std::deque< SPtr_A v;
v.push_back( SPtr_A(new A) );
}

In the above, the responsability of the heap allocation is transferred
to the vector.
The ultimate reason, in the end, for such a recommendation, astonishly
enough, is that it is easier and safer to program without new/delete.
Consider:

#include <boost/shared_ptr.hpp>

struct Base { };
struct Derived : public Base { };

int main()
{
// Base* p_base = new Derived;
// delete p_base; // memory leak, ~Base() is not virtual
boost::shared_ptr< Base sp(new Derived);
}

If you did the above with new/delete, you'ld get a leak because the
Base class doesn't have a virtual destructor. Yet that is not an issue
with boost::shared_ptr, which correctly invokes both c~tors
polymorphicly for you.

Dec 14 '06 #15

Salt_Peter wrote:
Vyacheslav Kononenko wrote:
Salt_Peter wrote:
I'ld suggest writing code without new/delete. You'll find that such
code is much easier to write and maintain.
Hmm very strange recommendation. I would hardly imagine any nontrivial
C++ application, that does not use objects from the heap.

Who said not to use the heap? Since when do you require new/delete for
the heap? Entire applications can be written, and are written, without
a single delete - and those applications are rock solid.
Whats stopping you from using a smart_pointer like std::auto_ptr,
boost::shared_ptr or boost::shared_array, etc? Why not let a std
container provide RAII for you? Even in the case where you must
allocate elements, why deal with the headaches of deallocation when you
can do as follows:

#include <deque>
#include <boost/shared_ptr.hpp>

class A { ];
int main()
{
typedef boost::shared_ptr< A SPtr_A;
std::deque< SPtr_A v;
v.push_back( SPtr_A(new A) );
}

In the above, the responsability of the heap allocation is transferred
to the vector.
No more so than it was before. You still called 'new' thus you still
performed the heap allocation of your new A. This heap memory has been
handed off to an RAII object for deallocation but you still allocated
it and the vector isn't the one responsible...to make that clear make a
copy of your smart pointer and see if it's still pointing at a valid
object after the vector is destroyed.
The ultimate reason, in the end, for such a recommendation, astonishly
enough, is that it is easier and safer to program without new/delete.
Consider:

#include <boost/shared_ptr.hpp>

struct Base { };
struct Derived : public Base { };

int main()
{
// Base* p_base = new Derived;
// delete p_base; // memory leak, ~Base() is not virtual
boost::shared_ptr< Base sp(new Derived);
}

If you did the above with new/delete, you'ld get a leak because the
Base class doesn't have a virtual destructor. Yet that is not an issue
with boost::shared_ptr, which correctly invokes both c~tors
polymorphicly for you.
smart pointers cannot take care of all situations when this is a
problem. Also, boost::shared_ptr is the only one that will correctly
deal with the object when finished, but I believe this is only true if
the pointer passed into it was a Derived* (the "polymorphism" in this
case is static). In other words, a non-virtual destructor in a
polymorphic base class is a problem no matter what.

int main()
{
Base * b = new Derived;
boost::shared_ptr<Basesb = boost::shared_ptr<Base>(b); //
} // Base's destructor called.

Dec 14 '06 #16

Salt_Peter wrote:
Who said not to use the heap? Since when do you require new/delete for
the heap? Entire applications can be written, and are written, without
a single delete - and those applications are rock solid.
I totally agree with this statement. Yes they can be written. But it
does not mean that all of them must be or should be written this way.
Also it does not mean that every application will benefit of this.
Otherway we can forget about C++ and migrate to java.
Whats stopping you from using a smart_pointer like std::auto_ptr,
boost::shared_ptr or boost::shared_array, etc? Why not let a std
container provide RAII for you?
Nothing stops me. And I am using it. I am also aware that smart
pointers are not a silver bullet and there are situations when they do
not work well. But anyway pointers and memory management is base for
C++ and to recommend a beginner to avoid learn it is strange. There is
comp.lang.java for that.

Dec 14 '06 #17

Noah Roberts wrote:
Salt_Peter wrote:
Vyacheslav Kononenko wrote:
Salt_Peter wrote:
I'ld suggest writing code without new/delete. You'll find that such
code is much easier to write and maintain.
>
Hmm very strange recommendation. I would hardly imagine any nontrivial
C++ application, that does not use objects from the heap.
Who said not to use the heap? Since when do you require new/delete for
the heap? Entire applications can be written, and are written, without
a single delete - and those applications are rock solid.
Whats stopping you from using a smart_pointer like std::auto_ptr,
boost::shared_ptr or boost::shared_array, etc? Why not let a std
container provide RAII for you? Even in the case where you must
allocate elements, why deal with the headaches of deallocation when you
can do as follows:

#include <deque>
#include <boost/shared_ptr.hpp>

class A { ];
int main()
{
typedef boost::shared_ptr< A SPtr_A;
std::deque< SPtr_A v;
v.push_back( SPtr_A(new A) );
}

In the above, the responsability of the heap allocation is transferred
to the vector.

No more so than it was before. You still called 'new' thus you still
performed the heap allocation of your new A. This heap memory has been
handed off to an RAII object for deallocation but you still allocated
it and the vector isn't the one responsible...to make that clear make a
copy of your smart pointer and see if it's still pointing at a valid
object after the vector is destroyed.
Yes, thats right, it is a heap allocation. The difference is that if
something occurs, like an exception thrown, your deletes won't get
skipped. If something exceptional throws the context, the vector gets
zapped, which invokes the shared_ptr's destructors for each element.
Thats clearly remitting the responsability of deallocation to that
vector (in the same way that relying on the stack for those elements is
RAII) . Obviously, if you make a copy of a shared_ptr, it won't be
destroyed (reference count).
>
The ultimate reason, in the end, for such a recommendation, astonishly
enough, is that it is easier and safer to program without new/delete.
Consider:

#include <boost/shared_ptr.hpp>

struct Base { };
struct Derived : public Base { };

int main()
{
// Base* p_base = new Derived;
// delete p_base; // memory leak, ~Base() is not virtual
boost::shared_ptr< Base sp(new Derived);
}

If you did the above with new/delete, you'ld get a leak because the
Base class doesn't have a virtual destructor. Yet that is not an issue
with boost::shared_ptr, which correctly invokes both c~tors
polymorphicly for you.

smart pointers cannot take care of all situations when this is a
problem. Also, boost::shared_ptr is the only one that will correctly
deal with the object when finished, but I believe this is only true if
the pointer passed into it was a Derived* (the "polymorphism" in this
case is static). In other words, a non-virtual destructor in a
polymorphic base class is a problem no matter what.

int main()
{
Base * b = new Derived;
boost::shared_ptr<Basesb = boost::shared_ptr<Base>(b); //
} // Base's destructor called.
no, sir. The above does the following:

~Derived()
~Base()

And it does so even if no virtual functions exist. To see how boost
does that: see boost's checked_delete.hpp.

Dec 15 '06 #18

Vyacheslav Kononenko wrote:
Salt_Peter wrote:
Who said not to use the heap? Since when do you require new/delete for
the heap? Entire applications can be written, and are written, without
a single delete - and those applications are rock solid.

I totally agree with this statement. Yes they can be written. But it
does not mean that all of them must be or should be written this way.
Also it does not mean that every application will benefit of this.
Otherway we can forget about C++ and migrate to java.
I'm not suggesting that a GC is needed, its not and smart_ptrs are a
better system. There is a growing inclination in the C++ community to
discourage heap allocations that don't use smart pointers with the
exception of self-recovering classes (thats how STL containers are
designed). They keep the programmer conscious and disciplined about
those allocations and simplifies the code.
Too many newbies think its ok to new overhere, cross fingers, and
delete overthere without understanding that allocations and
deallocations are not meant to be distributed (or ignored).
>
Whats stopping you from using a smart_pointer like std::auto_ptr,
boost::shared_ptr or boost::shared_array, etc? Why not let a std
container provide RAII for you?

Nothing stops me. And I am using it. I am also aware that smart
pointers are not a silver bullet and there are situations when they do
not work well. But anyway pointers and memory management is base for
C++ and to recommend a beginner to avoid learn it is strange. There is
comp.lang.java for that.
Dec 15 '06 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
by: Norm | last post by:
Could someone explain for me what is happening here? char *string; string = new char; string = "This is the string"; cout << string << std::endl; The output contains (This the string) even...
14
by: dumboo | last post by:
hi there i m little bit confused over the following problem, i have understood wt the following code is doing...but not able to get the actual techinical stuff.....i have had a lot of hot debate...
110
by: Mr A | last post by:
Hi! I've been thinking about passing parameteras using references instead of pointers in order to emphasize that the parameter must be an object. Exemple: void func(Objec& object); //object...
4
by: z_learning_tester | last post by:
I'm reading the MS press C# book and there seems to be a contradiction. Please tell me which one is correct, 1 or 2. Thanks! Jeff 1. First it gives the code below saying that it prints 0 then...
10
by: yogeshmk | last post by:
I need to break a longer string (with strtok()) and store the smaller strings in an array. since the number of small strings is not fixed/known, I cannot use a declaration like char *format, so I...
4
by: Jon Slaughter | last post by:
I'm reading a book on C# and it says there are 4 ways of passing types: 1. Pass value type by value 2. Pass value type by reference 3. Pass reference by value 4. Pass reference by reference. ...
3
by: michael | last post by:
Hi All, How do I pass a reference to a pointer and update the pointer in the function? I have: void goGetString(char *str){ string inString; cin >inString; str = new char;
11
by: venkatagmail | last post by:
I have problem understanding pass by value and pass by reference and want to how how they are or appear in the memory: I had to get my basics right again. I create an array and try all possible...
4
by: S. | last post by:
Hi all, I have the requirement that I must pass-by-reference to my function addStudent() and getAge() functions where my getAge() function is within the addStudent() function. I am able to...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
1
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.