Hi,
I observed a behavior that I didn't expect: I have a vector of sets. I
iterate over the first of these sets, and while I iterate over it, I
add another set at the end of the vector. I thought that shouldn't
affect the first set I am iterating over, but it does, and I get a
segmentation fault.
See the example program below.
It works fine if I make set0 a *copy* of v[0], instead of a reference
or a pointer, but I would rather not copy it (this routine is called
very often in my program and I don't see why I should make an
expensive copy).
How can I fix this? Thanks!
int main(int argc, char** argv){
std::vector<std::set<int v;
std::set<ints;
s.insert(1);
s.insert(2);
v.push_back(s);
std::set<int>& set0 = v[0]; // using reference because we don't want
to copy to local var (too expensive)
for(std::set<int>::const_iterator it = set0.begin(); it !=
set0.end(); ++it){
std::cout << *it << std::endl;
std::set<inttmp;
tmp.insert(10);
v.push_back(tmp); // will be v[1], so it shouldn't change set0 or
its
iterator?
}
return 0;
}
As output I get:
1
10
1
10
1
10
....
Segmentation fault 3 1459
Markus Dehmann wrote:
Hi,
I observed a behavior that I didn't expect: I have a vector of sets. I
iterate over the first of these sets, and while I iterate over it, I
add another set at the end of the vector. I thought that shouldn't
affect the first set I am iterating over, but it does, and I get a
segmentation fault.
It does not affect the first set _as a value_. However, it affects the first
set _as an object (region of memory)_ because inserting an element into the
vector can trigger a re-allocation of the vector and then all current
elements are moved around.
>
See the example program below.
It works fine if I make set0 a *copy* of v[0], instead of a reference
or a pointer, but I would rather not copy it (this routine is called
very often in my program and I don't see why I should make an
expensive copy).
How can I fix this? Thanks!
int main(int argc, char** argv){
std::vector<std::set<int v;
std::set<ints;
s.insert(1);
s.insert(2);
v.push_back(s);
std::set<int>& set0 = v[0]; // using reference because we don't want
to copy to local var (too expensive)
You are using a reference. Insertions into a vector can invalidate all
references, pointers, and iterators into the vector (for the reasons
mentioned above).
for(std::set<int>::const_iterator it = set0.begin(); it !=
set0.end(); ++it){
std::cout << *it << std::endl;
std::set<inttmp;
tmp.insert(10);
v.push_back(tmp); // will be v[1], so it shouldn't change set0 or
its
iterator?
}
return 0;
}
As output I get:
1
10
1
10
1
10
...
Segmentation fault
Yup, that the undefined behavior from using an invalidated reference.
Your options include:
a) Use std::list instead of std::vector.
b) Instead of inserting the new sets right away, put them on hold.
c) Use std::vector< some_smart_pointer< std::set<int >.
Best
Kai-Uwe Bux
On 9 Jun, 23:43, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Markus Dehmann wrote:
Hi,
I observed a behavior that I didn't expect: I have a vector of sets. I
iterate over the first of these sets, and while I iterate over it, I
add another set at the end of the vector. I thought that shouldn't
affect the first set I am iterating over, but it does, and I get a
segmentation fault.
[snip]
Your options include:
a) Use std::list instead of std::vector.
b) Instead of inserting the new sets right away, put them on hold.
c) Use std::vector< some_smart_pointer< std::set<int >.
Depending on your program, you may get away with
d) If possible, use the reserve() member function of vector to ensure
that no reallocation takes place.
Like this:
std::vector<std::set<int v;
v.reserve(10) // If you know beforehand that no more than 10
elements will be inserted.
Note that you can also check size() vs. capacity() to determine
whether a push_back() will trigger a reallocation (invalidating all
references)
DP
On Jun 9, 11:43 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Markus Dehmann wrote:
I observed a behavior that I didn't expect: I have a vector
of sets. I iterate over the first of these sets, and while I
iterate over it, I add another set at the end of the vector.
I thought that shouldn't affect the first set I am iterating
over, but it does, and I get a segmentation fault.
It does not affect the first set _as a value_. However, it
affects the first set _as an object (region of memory)_
because inserting an element into the vector can trigger a
re-allocation of the vector and then all current elements are
moved around.
See the example program below.
It works fine if I make set0 a *copy* of v[0], instead of a reference
or a pointer, but I would rather not copy it (this routine is called
very often in my program and I don't see why I should make an
expensive copy).
How can I fix this? Thanks!
int main(int argc, char** argv){
std::vector<std::set<int v;
std::set<ints;
s.insert(1);
s.insert(2);
v.push_back(s);
std::set<int>& set0 = v[0]; // using reference because we don't want
to copy to local var (too expensive)
You are using a reference. Insertions into a vector can
invalidate all references, pointers, and iterators into the
vector (for the reasons mentioned above).
for(std::set<int>::const_iterator it = set0.begin(); it !=
set0.end(); ++it){
std::cout << *it << std::endl;
std::set<inttmp;
tmp.insert(10);
v.push_back(tmp); // will be v[1], so it shouldn't change set0 or
its
iterator?
}
return 0;
}
As output I get:
1
10
1
10
1
10
...
Segmentation fault
Yup, that the undefined behavior from using an invalidated reference.
Your options include:
a) Use std::list instead of std::vector.
b) Instead of inserting the new sets right away, put them on hold.
c) Use std::vector< some_smart_pointer< std::set<int >.
d) Use v[0] each time you need it, rather than saving the
reference.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Justin |
last post by:
Hi! i'm a beginner user of c++ and i need some help. I use visual c++
6.0 on a p4 under windows 2000.
First, i read a text file with 3 fields: gestionnal age (GA), birth
weight (BW) and...
|
by: Matt Garman |
last post by:
Is there any difference, performance-wise, accessing elements of a
vector using iterators or the subscript operator?
In other words, say I have a vector of strings:
vector<string> strvec;
...
|
by: fudmore |
last post by:
Hello Everybody.
I have a Segmentation fault problem. The code section at the bottom
keeps throwing a Segmentation fault when it enters the IF block for the
second time.
const int...
|
by: Adam Hartshorne |
last post by:
Hi All,
I have the following problem, and I would be extremely grateful if
somebody would be kind enough to suggest an efficient solution to it.
I create an instance of a Class A, and...
|
by: Bob |
last post by:
Here's what I have:
void miniVector<T>::insertOrder(miniVector<T>& v,const T& item)
{
int i, j;
T target;
vSize += 1;
T newVector;
newVector=new T;
|
by: Piotr |
last post by:
In effective STL, it said one should not use vector<bool> but use
dequeue<bool> instead.
But can dequeue<bool> has random access iterator? and I do this?
dequeue<bool> myboolarray;
if...
|
by: Dilip |
last post by:
If you reserve a certain amount of memory for a std::vector, what
happens when a reallocation is necessary because I overshot the limit?
I mean, say I reserve for 500 elements, the insertion of...
|
by: Jess |
last post by:
Hello,
I tried to clear a vector "v" using "v.clear()". If "v" contains
those objects that are non-built-in (e.g. string), then "clear()" can
indeed remove all contents. However, if "v"...
|
by: Matteo Migliore |
last post by:
Hi!
I've to scale a vector of numbers of size N to a vector of size M.
The trasformation is like a zoom on images but I need on a vector.
The second size can be M >= N or M <= N, M 0.
The...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
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...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
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...
| |