473,849 Members | 1,779 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

A problem when using a reference to a vector of a class with a pointer member to an array

Dear Programmers,

I have a class with a pointer to an array. In the destructor, I just
freed this pointer. A problem happens if I define a reference to a
vector of this kind of class. The destruction of the assigned memory
seems to call the class destructor more than once. I don't know the
reason or whether I used the vector class correctly. Attached is my
program. Thanks for your help.

Regards,
Brian

Run Result:
$ ./a.out
done
*** glibc detected *** double free or corruption (top): 0x08fa40a0 ***
Aborted

Code:
#include <iostream>
#include <vector>

using namespace std;

class ArrayWrap
{
public:
char * pt_ch;
ArrayWrap()
{
pt_ch = new char[100];
}
~ArrayWrap() {
delete[] pt_ch; // if delete this statement, no error then,
// but not a reasonable design
}
};

int main()
{
ArrayWrap dum;
ArrayWrap & rdum = dum;
vector<ArrayWra pdummy(10);
vector<ArrayWra p& refdummy = dummy;

cout << "done" << endl;
return 0;
}

Oct 19 '06 #1
11 1929
Brian wrote:
Dear Programmers,

I have a class with a pointer to an array. In the destructor, I just
freed this pointer. A problem happens if I define a reference to a
vector of this kind of class. The destruction of the assigned memory
seems to call the class destructor more than once. I don't know the
reason or whether I used the vector class correctly. Attached is my
program. Thanks for your help.

Regards,
Brian

Run Result:
$ ./a.out
done
*** glibc detected *** double free or corruption (top): 0x08fa40a0 ***
Aborted

Code:
#include <iostream>
#include <vector>

using namespace std;

class ArrayWrap
{
public:
char * pt_ch;
ArrayWrap()
{
pt_ch = new char[100];
}
~ArrayWrap() {
delete[] pt_ch; // if delete this statement, no error then,
// but not a reasonable design
}
};

int main()
{
ArrayWrap dum;
ArrayWrap & rdum = dum;
vector<ArrayWra pdummy(10);
vector<ArrayWra p& refdummy = dummy;

cout << "done" << endl;
return 0;
}
Your wrapper class needs a copy constructor. See the third bullet about
the law of the big three here:

http://www.parashift.com/c++-faq-lit...html#faq-27.10

But, why not just use vector< vector<char or vector<string(s ee
http://www.parashift.com/c++-faq-lit...tml#faq-34.1)?

Cheers! --M

Oct 19 '06 #2
Thanks a lot. It works. This is a simplified program from my real
work to reproduce the problem. We can't use vector< vector<char or
vector<stringbe cause we need to write what the pointer points to as a
whole body to a tape in one unbuffered write() for speed concern. I
don't know any better way.

However, I still don't understand the reason for the need of copy
constructor. During the lunch, I came out of the idea that why I don't
just use a pointer to the established vector in stead of a reference.
To my surprise, it doesn't work either without a copy constructor. I
don't get it. I didn't make any copy, but just made a pointer or a
reference referring to the established vector object. I don't see
where a copy was made. I didn't put anything in the copy constructor
and it still works. Is this a requirement that the standard library
has? Are there some hidden copy operations made when we define a
vector reference or pointer?

Thanks,
Brian

mlimber wrote:
Your wrapper class needs a copy constructor. See the third bullet about
the law of the big three here:

http://www.parashift.com/c++-faq-lit...html#faq-27.10

But, why not just use vector< vector<char or vector<string(s ee
http://www.parashift.com/c++-faq-lit...tml#faq-34.1)?

Cheers! --M
Oct 19 '06 #3
"Brian" <su******@myrea lbox.comwrote in message
news:11******** **************@ b28g2000cwb.goo glegroups.com.. .
Thanks a lot. It works. This is a simplified program from my real
work to reproduce the problem. We can't use vector< vector<char or
vector<stringbe cause we need to write what the pointer points to as a
whole body to a tape in one unbuffered write() for speed concern. I
don't know any better way.

However, I still don't understand the reason for the need of copy
constructor. During the lunch, I came out of the idea that why I don't
just use a pointer to the established vector in stead of a reference.
To my surprise, it doesn't work either without a copy constructor. I
don't get it. I didn't make any copy, but just made a pointer or a
reference referring to the established vector object. I don't see
where a copy was made. I didn't put anything in the copy constructor
and it still works. Is this a requirement that the standard library
has? Are there some hidden copy operations made when we define a
vector reference or pointer?

Thanks,
Brian

mlimber wrote:
>Your wrapper class needs a copy constructor. See the third bullet about
the law of the big three here:

http://www.parashift.com/c++-faq-lit...html#faq-27.10

But, why not just use vector< vector<char or vector<string(s ee
http://www.parashift.com/c++-faq-lit...tml#faq-34.1)?

Cheers! --M
Please don't top post. Please supply more context from previous post.

int main()
{
ArrayWrap dum;
ArrayWrap & rdum = dum;
vector<ArrayWra pdummy(10);
// I believe the previous line is your problem

vector<ArrayWra p& refdummy = dummy;

cout << "done" << endl;
return 0;
}

Vectors tend to be a pain this way. It seems (to me) that when you put an
item into a vector it first creates it into a temporary, then copies the
temporary into the vector. So when the temporary gets destroyed, it runs
the destructor and you're hozed.

I've run into this problem before with classes that are not copyable (
unique objects loaded that can't be copied, or are just a waste of time to
copy). The way I've solved this is to make a private copy constructor (so
it *can't* be copied) then to make my vector into pointers.

vector<ArrayWra p*dummy;
for ( i = 0; i < 10; i++ )
ArrayWrap.push_ back( new ArrayWrap );
// code

for ( vector<ArrayWra p>::iterator it = ArrayWrap.begin (); it !=
ArrayWrap.end() ; ++it )
delete (*it); // double check syntax of this
Oct 19 '06 #4

Jim Langston wrote in message ...
>
vector<ArrayWr ap*dummy;
for ( i = 0; i < 10; i++ )
Got a headache today, Jim? Did you mean?

// ArrayWrap.push_ back( new ArrayWrap );
dummy.push_back ( new ArrayWrap );

// <GBeen there, done that. <G>
>// code
// >for ( vector<ArrayWra p>::iterator it = ArrayWrap.begin (); it !=
// >ArrayWrap.end( ); ++it )
for( vector<ArrayWra p*>::iterator it( dummy.begin() ); it !=
dummy.end(); ++it )
delete (*it); // double check syntax of this
Yep, looks same as one I use:
// ------------------------------------
template<class Seqvoid PurgeCon( Seq &cont ){
typename Seq::iterator it;
for( it = cont.begin(); it != cont.end(); ++it ){
delete *it;
*it = 0; // just in case it's called twice.
} // for(it)
} // template<class Seqvoid PurgeCon(Seq&)
// ------------------------------------

PurgeCon( dummy );

--
Bob R
POVrookie
Oct 20 '06 #5
"BobR" <Re***********@ worldnet.att.ne twrote in message
news:4c******** *************@b gtnsc05-news.ops.worldn et.att.net...
>
Jim Langston wrote in message ...
>>
vector<ArrayW rap*dummy;
for ( i = 0; i < 10; i++ )

Got a headache today, Jim? Did you mean?

// ArrayWrap.push_ back( new ArrayWrap );
dummy.push_back ( new ArrayWrap );

// <GBeen there, done that. <G>
Heh, yeah, nice catch.
>>// code
// >for ( vector<ArrayWra p>::iterator it = ArrayWrap.begin (); it !=
// >ArrayWrap.end( ); ++it )
for( vector<ArrayWra p*>::iterator it( dummy.begin() ); it !=
dummy.end(); ++it )
Me and ArrayWrap again instead of dummy. lo.

I notice you use it (dummy.begin()) to construct the iterator. I've never
known I could do this, but does it really save anything?
>
> delete (*it); // double check syntax of this

Yep, looks same as one I use:
// ------------------------------------
template<class Seqvoid PurgeCon( Seq &cont ){
typename Seq::iterator it;
for( it = cont.begin(); it != cont.end(); ++it ){
delete *it;
Yet, here you don't use the initialization, why?
*it = 0; // just in case it's called twice.
} // for(it)
} // template<class Seqvoid PurgeCon(Seq&)
// ------------------------------------

PurgeCon( dummy );

Oct 20 '06 #6

"Brian" <su******@myrea lbox.comwrote in message
news:11******** **************@ b28g2000cwb.goo glegroups.com.. .
Thanks a lot. It works. This is a simplified program from my real
work to reproduce the problem. We can't use vector< vector<char or
vector<stringbe cause we need to write what the pointer points to as a
whole body to a tape in one unbuffered write() for speed concern. I
don't know any better way.
However, I still don't understand the reason for the need of copy
constructor.

Not understanding what you really did (please post your updated class), the
vector requires that your object are copyable, and to make sure no bugs
exist, the objects should be able to be copied safely with no issues. Your
original ArrayWrap class does not satisfy the "safely copyable" requirement
(although it is copyable).

int main()
{
ArrayWrap a;
ArrayWrap b = a;
}

Try this with your original class, or with the class that you have changed
it to. Does this work correctly (i.e. no memory leaks, crashes, double
deletion errors, etc.)? It won't work with your original class, since at
the end of main(), a double deletion error will occur when object a and b
are destroyed.

That's simply what vector is doing, and if there are bugs with the simple
code above, then there will be bugs when vector gets its hands on it.

- Paul

Oct 20 '06 #7

Brian wrote:
Thanks a lot. It works. This is a simplified program from my real
work to reproduce the problem. We can't use vector< vector<char or
vector<stringbe cause we need to write what the pointer points to as a
whole body to a tape in one unbuffered write() for speed concern. I
don't know any better way.
When you say "what the pointer points to" are you talking about the
pointer in your ArrayWrap class? If so then what you need does not
preclude you replacing ArrayWrap with vector<charand replacing
vector<ArrayWra pwith vector<vector<c har. "What the pointer points
to" in your ArrayWrap class becomes "the contents of a vector<char>".
You can very easily get at the contents of a vector<charfor your
single unbuffered write.

If I have misunderstood you when you say "what the pointer points to"
please clarify as there may still be a better solution.

Gavin Deane

Oct 20 '06 #8

Jim Langston wrote in message ...
>"BobR" wrote in message
>>
Jim Langston wrote in message ...
>>>
vector<Array Wrap*dummy;
for ( i = 0; i < 10; i++ )

Got a headache today, Jim? Did you mean?
// ArrayWrap.push_ back( new ArrayWrap );
dummy.push_back ( new ArrayWrap );
// <GBeen there, done that. <G>

Heh, yeah, nice catch.
>>>// code
// >for ( vector<ArrayWra p>::iterator it = ArrayWrap.begin (); it !=
// >ArrayWrap.end( ); ++it )
for( vector<ArrayWra p*>::iterator it( dummy.begin() ); it !=
dummy.end(); ++it )

Me and ArrayWrap again instead of dummy. lo.

I notice you use it (dummy.begin()) to construct the iterator. I've never
known I could do this, but does it really save anything?
Sure, if you did it a million times in your program and optimazation was off,
it could save a second in runtime! <GActually, I was just being a
smart-ass.
If you are used to assignment (=), you should be consistant and always use
assignment in your code. Mostly a 'style choice'.

You seldom see:

class Mine{.....};
Mine My = 12345;
.....but, usually:
Mine My(12345);

.....so....

int Num(12345);

.... is my choice of style. <G>
>
>>
>> delete (*it); // double check syntax of this

Yep, looks same as one I use:
// ------------------------------------
template<cla ss Seqvoid PurgeCon( Seq &cont ){
// typename Seq::iterator it;
// for( it = cont.begin(); it != cont.end(); ++it ){

Yet, here you don't use the initialization, why?
Uuuh, old code? Stole the code from someone and didn't change it?

for( typename Seq::iterator it( cont.begin() ); it != cont.end(); ++it){

// typename Seq::iterator it( cont.begin() );
// for( ; it != cont.end(); ++it ){ delete *it; *it = 0; }

Newbies, see:
"Thinking In C++", Volume 2: Practical Programming (Bruce Eckel, Chuck
Allison)
Chap. 5: Templates in Depth (sub "The typename keyword")
http://www.mindview.net/Books/TICPP/...ngInCPP2e.html
.....for why the 'typename' is needed. (or look it up in *your* book)
> delete *it;
*it = 0; // just in case it's called twice.
} // for(it)
} // template<class Seqvoid PurgeCon(Seq&)
// ------------------------------------

PurgeCon( dummy );

[ I'm not a expert, feel free to correct me. ]
--
Bob R
POVrookie
Oct 20 '06 #9
Dear Jim,

Thank you very much. Your explanation is right. It was not the
reference or pointer that caused the problem but the place your pointed
out.

The vector constructor does create a temporary object and copy it to
all the vector members and destroy it. I put some cout statements in
the constructor, copy constructor and destructor and got relevant
information.

I said that when I put nothing in the copy constructor it still works.
I was wrong. It only works when I don't access anything within the
object, otherwise it causes segmentation error because all its members
will have no valid value if nothing was done in the copy constructor.

I attached my updated program below for context and left some comments.
Now I don't need your technique of pointers. I will keep it in mind
in case needed. Thanks a lot.

Regards,
Brian

Jim Langston wrote:
>
Please don't top post. Please supply more context from previous post.

int main()
{
ArrayWrap dum;
ArrayWrap & rdum = dum;
vector<ArrayWra pdummy(10);
// I believe the previous line is your problem

vector<ArrayWra p& refdummy = dummy;

cout << "done" << endl;
return 0;
}

Vectors tend to be a pain this way. It seems (to me) that when you put an
item into a vector it first creates it into a temporary, then copies the
temporary into the vector. So when the temporary gets destroyed, it runs
the destructor and you're hozed.

I've run into this problem before with classes that are not copyable (
unique objects loaded that can't be copied, or are just a waste of time to
copy). The way I've solved this is to make a private copy constructor (so
it *can't* be copied) then to make my vector into pointers.

vector<ArrayWra p*dummy;
for ( i = 0; i < 10; i++ )
ArrayWrap.push_ back( new ArrayWrap );
// code

for ( vector<ArrayWra p>::iterator it = ArrayWrap.begin (); it !=
ArrayWrap.end() ; ++it )
delete (*it); // double check syntax of this
------------------------------------------------------------------------------------------------------
#include <iostream>
#include <vector>

using namespace std;

class ArrayWrap
{
public:
char * pt_ch;
ArrayWrap()
{
pt_ch = new char[100];
pt_ch[0] = 'b';
cout << "create dummy" << endl;
}

ArrayWrap(const ArrayWrap & AnArray)
{
pt_ch = new char[100]; // this made copy's pt_ch valid
pt_ch[0] = AnArray.pt_ch[0]; // this assigned values to
// the copy.
cout << "copy dummy" << endl;
}

~ArrayWrap()
{
delete[] pt_ch;
cout << "destruct dummy" << endl;
}

int print()
{
cout << pt_ch[0] << endl;
return 1;
}
};

int main()
{
ArrayWrap dum;
vector<ArrayWra pdummy(5); // copy constructor
// is needed here, otherwise
// pt_ch of dummy[i] points
// to destroyed temporary
// ArrayWrap object
vector<ArrayWra p& refdummy = dummy;
vector<ArrayWra p* pdummy;
dummy[0].print(); // this will cause segmentation
// error if copy constructors
// first two statements is omitted
cout << "done" << endl;
return 0;
}

Oct 27 '06 #10

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

Similar topics

9
3399
by: J. Campbell | last post by:
I'm comfortable with arrays from previous programming, and understand the advantages of c++ vectors...I just don't understand how to use them :~( Can you help me to use a vector<string> in the following compilable example instead of the string* array? Thanks, Joe #include <iostream>
3
1787
by: Tony Johansson | last post by:
Hello Experts!! I have two small classes called Intvektor and Matris shown below and a main. Class Intvektor will create a one dimension array of integer by allocate memory dynamically as you can see in the constructor. Class Matris should create a matris by using class Intvektor. So what I want to have is a pointer to an array of Intvektor and in each positionindex in this array will I have a pointer to an array of Intvektor in this...
4
1383
by: Alan | last post by:
I have a class, "event_list", derived from the template class "vector." I extended it with a method, "write" for this new class. Here's its definition: class event_list : public vector<Event> { public: void write (ofstream &filename, format_type format, int start, int end); };
20
2137
by: Joe Van Dyk | last post by:
Is there some rule of thumb about when to use pointers to an object and when to use a reference* to an object when a class needs to have objects as data members? Example: class A { B* b_ptr; B b; vector<B*> vector_ptrs;
7
2963
by: fakeprogress | last post by:
For a homework assignment in my Data Structures/C++ class, I have to create the interface and implementation for a class called Book, create objects within the class, and process transactions that manipulate (and report on) members of the class. Interface consists of: - 5 private variables char author; char title; char code;
29
3664
by: shuisheng | last post by:
Dear All, The problem of choosing pointer or reference is always confusing me. Would you please give me some suggestion on it. I appreciate your kind help. For example, I'd like to convert a string to a integer number. bool Convert(const string& str, int* pData); bool Convert(const string& str, int& data);
15
2180
by: Jess | last post by:
Hello, Sometimes declarations are all what we need when we define/declare classes (or functions?), but sometimes we need definitions. I learned that if we define a class (B) that has an object (a_obj) of a class type (A), then we need to define A as well, but if B has a pointer to A, then we only need to forward declare A. I was told this is because the compiler needs to see the implemenation of A when allocating memory for a_obj. ...
4
2067
by: abir | last post by:
I am matching a template, and specializing based of a template, rather than a single class. The codes are like, template<template<typename T,typename Alloc = std::allocator<T> class pix{ }; template<> class pix<vector>{
9
2066
by: itdevries | last post by:
Hi, I've ran into some trouble with an overloaded + operator, maybe someone can give me some hints what to look out for. I've got my own custom vector class, as a part of that I've overloaded the + operator by means of a friend function. Everything worked fine until I decided to use a variable array size (by using new/delete), now I get an error when a temporary object is deleted (e.g. after addition), the error occurs at the delete...
0
9893
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9738
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10723
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10349
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7894
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5735
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5921
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4544
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4139
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.