I'm using an STL map in my code.
My application sometimes tries to delete things twice from the map.
This leads to a crash in my current code. The problem is probably the
way I check whether it is necessary to delete something (line 44 and 52
in below code).
In the below code the problem is demonstrated, line 65 will cause a
segmentation fault.
1 #include <iostream>
2 #include <cstdlib>
3 #include <map>
4
5 using namespace std;
6
7 class MyClass
8 {
9 public:
10 MyClass(int);
11 ~MyClass();
12 void show();
13 private:
14 int nr_;
15 };
16
17 MyClass::MyClass(int nr) : nr_(nr)
18 {
19 cout << "MyClass: " << nr_ << " constructed" << endl;
20 }
21
22 MyClass::~MyClass()
23 {
24 cout << "MyClass: " << nr_ << " destructed" << endl;
25 }
26
27 void MyClass::show()
28 {
29 cout << "Show this MyClass: " << nr_ << endl;
30 }
31
32 typedef map<int, MyClass *> RtdmCyclicTimerMap;
33
34 int main(void)
35 {
36 RtdmCyclicTimerMap cyclicRtdmTimer_;
37 map<int, MyClass *>::const_iterator cyclicRtdmIt;
38
39 // create 1 & 2
40 cyclicRtdmTimer_[1] = new MyClass(11);
41 cyclicRtdmTimer_[2] = new MyClass(22);
42
43 // delete 2
44 if (cyclicRtdmTimer_[2]) {
45 delete cyclicRtdmTimer_[2];
46 cyclicRtdmTimer_.erase(2);
47 } else {
48 cout << "delete 2 failed" << endl;
49 }
50
51 // delete 2 AGAIN
52 if (cyclicRtdmTimer_[2]) {
53 delete cyclicRtdmTimer_[2];
54 cyclicRtdmTimer_.erase(2);
55 } else {
56 cout << "delete 2[2] failed" << endl;
57 }
58
59 // show map -> NOW IT WILL CRASH
60 cout << endl << "going to show map entries" << endl;
61 for
(cyclicRtdmIt=cyclicRtdmTimer_.begin();cyclicRtdmI t!=cyclicRtdmTimer_.end();
++cyclicRtdmIt) {
62 int tKey = cyclicRtdmIt->first;
63 MyClass *mcPtr = cyclicRtdmIt->second;
64 cout << "map entry found: key=" << tKey << ", valP=" <<
mcPtr << ", val=";
65 mcPtr->show();
66 }
67 }
68
This is because line 52 somehow increases the internal map size from 1
to 2 entries.
Isn't it allowed to refer to deleted entries ?
Must it be done with an iterator ? 10 2115 bo*******@wanadoo.nl wrote: I'm using an STL map in my code. My application sometimes tries to delete things twice from the map. This leads to a crash in my current code. The problem is probably the way I check whether it is necessary to delete something (line 44 and 52 in below code).
Yes.
In the below code the problem is demonstrated, line 65 will cause a segmentation fault.
1 #include <iostream> 2 #include <cstdlib> 3 #include <map> 4 5 using namespace std; 6 7 class MyClass 8 { 9 public: 10 MyClass(int); 11 ~MyClass(); 12 void show(); 13 private: 14 int nr_; 15 }; 16 17 MyClass::MyClass(int nr) : nr_(nr) 18 { 19 cout << "MyClass: " << nr_ << " constructed" << endl; 20 } 21 22 MyClass::~MyClass() 23 { 24 cout << "MyClass: " << nr_ << " destructed" << endl; 25 } 26 27 void MyClass::show() 28 { 29 cout << "Show this MyClass: " << nr_ << endl; 30 } 31 32 typedef map<int, MyClass *> RtdmCyclicTimerMap; 33 34 int main(void) 35 { 36 RtdmCyclicTimerMap cyclicRtdmTimer_; 37 map<int, MyClass *>::const_iterator cyclicRtdmIt; 38 39 // create 1 & 2 40 cyclicRtdmTimer_[1] = new MyClass(11); 41 cyclicRtdmTimer_[2] = new MyClass(22); 42 43 // delete 2 44 if (cyclicRtdmTimer_[2]) { 45 delete cyclicRtdmTimer_[2]; 46 cyclicRtdmTimer_.erase(2); 47 } else { 48 cout << "delete 2 failed" << endl; 49 } 50 51 // delete 2 AGAIN 52 if (cyclicRtdmTimer_[2]) { 53 delete cyclicRtdmTimer_[2]; 54 cyclicRtdmTimer_.erase(2); 55 } else { 56 cout << "delete 2[2] failed" << endl; 57 } 58 59 // show map -> NOW IT WILL CRASH 60 cout << endl << "going to show map entries" << endl; 61 for
(cyclicRtdmIt=cyclicRtdmTimer_.begin();cyclicRtdmI t!=cyclicRtdmTimer_.end(); ++cyclicRtdmIt) { 62 int tKey = cyclicRtdmIt->first; 63 MyClass *mcPtr = cyclicRtdmIt->second; 64 cout << "map entry found: key=" << tKey << ", valP=" << mcPtr << ", val="; 65 mcPtr->show(); 66 } 67 } 68
This is because line 52 somehow increases the internal map size from 1 to 2 entries.
If operator[] doesn't find the element you are searching for, it creates
that element. Otherwise, line 40 and 41 couldn't work the way they do.
Since you don't assign anything to it in line 52, the value is probably
indeterminate and cannot be used with delete.
Must it be done with an iterator ?
Yes. Use the find() member function instead of operator[]. This will never
create elements. If the element is found, you get an iterator to it,
otherwise you get end().
> 51 // delete 2 AGAIN 52 if (cyclicRtdmTimer_[2]) {
The problem is here. This implicitly adds an element to the map and
initializes the pointer with NULL. When you try to dereference that pointer
later, you get a segfault.
You could use the following check instead:
if (cyclicRtdmTimer_.find(2) != cyclicRtdmTimer_.end()) {
Best wishes,
--
Andrei Tarassov
software engineer
Altiris, Inc. www.altiris.com
Rolf Magnus wrote: If operator[] doesn't find the element you are searching for, it creates that element. Otherwise, line 40 and 41 couldn't work the way they do. Since you don't assign anything to it in line 52, the value is probably indeterminate and cannot be used with delete.
Ok, forget that. Andrei is right. The newly added pointer is initialized to
a null pointer, and since you only remove it if it's not a null pointer, it
stays in your map. Later, when you try to dereference it, your program
crashes.
On Thu, 27 Apr 2006 12:34:27 +0300, Andrei Tarassov
<at*******@altiris.ee> wrote: 51 // delete 2 AGAIN 52 if (cyclicRtdmTimer_[2]) {
The problem is here. This implicitly adds an element to the map and initializes the pointer with NULL. When you try to dereference that pointer later, you get a segfault.
Examples like the above demonstrate that STL is designed for values
only, not for pointers. Unfortunately that fact is not conveyed in
most STL books and tutorials.
Best wishes,
Roland Pibinger bo*******@wanadoo.nl wrote: I'm using an STL map in my code. My application sometimes tries to delete things twice from the map. This leads to a crash in my current code. The problem is probably the way I check whether it is necessary to delete something (line 44 and 52 in below code). In the below code the problem is demonstrated, line 65 will cause a segmentation fault.
1 #include <iostream> 2 #include <cstdlib> 3 #include <map> 4 5 using namespace std; 6 7 class MyClass 8 { 9 public: 10 MyClass(int); 11 ~MyClass(); 12 void show(); 13 private: 14 int nr_; 15 }; 16 17 MyClass::MyClass(int nr) : nr_(nr) 18 { 19 cout << "MyClass: " << nr_ << " constructed" << endl; 20 } 21 22 MyClass::~MyClass() 23 { 24 cout << "MyClass: " << nr_ << " destructed" << endl; 25 } 26 27 void MyClass::show() 28 { 29 cout << "Show this MyClass: " << nr_ << endl; 30 } 31 32 typedef map<int, MyClass *> RtdmCyclicTimerMap; 33 34 int main(void) 35 { 36 RtdmCyclicTimerMap cyclicRtdmTimer_; 37 map<int, MyClass *>::const_iterator cyclicRtdmIt;
I recommend against using raw dummy pointers in an STL container.
I recommend you use a smart pointer like the following: http://axter.com/smartptr
The above smart pointer can be used with std::map, and will
automatically delete the pointee for you.
On 27 Apr 2006 12:40:16 -0700, "Axter" <go****@axter.com> wrote: I recommend against using raw dummy pointers in an STL container. I recommend you use a smart pointer like the following: http://axter.com/smartptr
The above smart pointer can be used with std::map, and will automatically delete the pointee for you.
The problem in the above code is an 'automatically' created NULL
pointer. Is your smart pointer smart enough to avoid that?
Regards,
Roland Pibinger
Andrei Tarassov schreef: 51 // delete 2 AGAIN 52 if (cyclicRtdmTimer_[2]) {
The problem is here. This implicitly adds an element to the map and initializes the pointer with NULL. When you try to dereference that pointer later, you get a segfault.
You could use the following check instead: if (cyclicRtdmTimer_.find(2) != cyclicRtdmTimer_.end()) {
thx yes, now I see.
indeed using find() everything works fine.
It's just that I thought I could use the "operator[]" in a *read-only*
way.
I guess I assumed the operator[] usage in the if statement could never
*write/change* something in the STL map.
Maybe I'm still a bit too C-minded.
thanks all for your insights.
Roland Pibinger wrote: On 27 Apr 2006 12:40:16 -0700, "Axter" <go****@axter.com> wrote:I recommend against using raw dummy pointers in an STL container. I recommend you use a smart pointer like the following: http://axter.com/smartptr
The above smart pointer can be used with std::map, and will automatically delete the pointee for you.
The problem in the above code is an 'automatically' created NULL pointer. Is your smart pointer smart enough to avoid that?
Actually yes.
The smart class has default logic that allows for assignment to a
default object in such cases. See following link, and comments for
smart_ptr<T>::set_default_object method: http://axter.com/smartptr/classsmart...b02795cf6a8c39
The smart pointer is specifically made to be used with the STL
containers, and it's far safer to use than using raw pointers. 44 if (cyclicRtdmTimer_[2]) { 45 delete cyclicRtdmTimer_[2];
It's good practice to think of operator[] as add/update operator for
non-const maps.
Not to be Not to be used as existence checker.
Regards,
Aman.
--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG
Roland Pibinger wrote: On Thu, 27 Apr 2006 12:34:27 +0300, Andrei Tarassov <at*******@altiris.ee> wrote:
51 // delete 2 AGAIN 52 if (cyclicRtdmTimer_[2]) {
The problem is here. This implicitly adds an element to the map and initializes the pointer with NULL. When you try to dereference that pointer later, you get a segfault.
Examples like the above demonstrate that STL is designed for values only, not for pointers.
No, it doesn't demostrate that. If the OP had stored values in the map, the
behavior wouldn't be undefined, but the result would still be incorrect (a
new value added to the map that wasn't supposed to be added). This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Adrian Parker |
last post by:
I have a PHP generated page which displays X many records. Each record has
a checkbox preceding it. The user checks several checkboxes, and hits a
delete button. All the corresponding records...
|
by: Dino |
last post by:
dear all,
i've created an application for a customer where the customer can upload
..csv-files into a specified ftp-directory. on the server, a php-script,
triggered by a cronjob, reads all the...
|
by: Travis Spencer |
last post by:
Hello,
I am trying to expose a C++ class to C clients using a C-compatible wrapper
API. While doing so, I hit a little snag. When a C client deletes one on my
classes using the provided delete...
|
by: Klemens |
last post by:
The linked table has a bigint in primary key columns.
I've read that service pack 8 on Jet should solve this but it didn't.
On patch1 options I only found to map timestamp to char(26) entry
for...
|
by: DaveDiego |
last post by:
I've had a user delete one of the client records, I do have a version of
the DB with all records intact before the deletion occured.
Whats the best approach to getting all the related records in...
|
by: jdph40 |
last post by:
On a form in Access 2002, I have a check box called DayCode. In the
AfterUpdate event, I have the following so when the check box is
ticked, the 1st day of the year will populate the text box...
|
by: ibiza |
last post by:
Hi SQL fans,
I realized that I often encounter the same situation in a relation
database context, where I really don't know what to do. Here is an
example, where I have 2 tables as follow:
...
|
by: BrianDP |
last post by:
I have a database with a split front end/back end. There is a key
table in the back end called Catalog, and it is sort of a central key
table for all sorts of things. It's a list of all the jobs...
|
by: Mark |
last post by:
Hi,
I would like to check if my object has been deleted or not, but my
program keeps crashing. Here's the simplified code (in infinite loop)
delete tetromino;
//if(tetromino==NULL)...
|
by: david720 |
last post by:
Error 3167 Record is deleted
And
Sometimes the main entry form displays a record in the form where all
fields are "#Delete"
Why do we get this error sometimes (about 2 times a week)?
It...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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: 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,...
|
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: 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...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
| |