Tried this program out of curiosity to understand behavior of shared_ptr over raw pointers. I hope the problem could be double delete but here I am facing other:
MyClass *raw_ptr = new MyClass();
shared_ptr<MyClass> sptr1(raw_ptr);
shared_ptr<MyClass> sptr2 = sptr1;
cout << sptr1.use_count() << endl; // prints 2
sptr1.reset(); // occurs Segmentation Fault here
Expected Behavior: reduce the count to 1 and moves control to next line.
Solved: Actual issue is at the next line in which sptr1 accessing the public class member MyClass::a which is invalid access after reset and hence the segfault. Confused because it didn't print the cout messages.
cout << "count: "<< sptr1.use_count()
<< "value: "<< sptr1->a;
There's no issues in that code. It is perfectly fine.
So either your compiler is broken, your development environment is broken, or there's other code there you're not showing us which is responsible for the crash.
Related
The program below is outputting unexpected use_count() value when shared pointer is printed using iterator de-reference of std::vector:
#include<iostream>
#include<memory>
#include<vector>
class A;
typedef std::shared_ptr<A> sharedPtr;
typedef std::vector<sharedPtr> sharedPtrVect;
typedef sharedPtrVect::const_iterator vectItr;
class A
{
public:
A(int inp): m_Val(inp) { /*std::cout << "*** A ctor called: " << m_Val << " ***" <<std::endl;*/ }
~A() { /*std::cout << "### A dtor called: " << m_Val << " ###" <<std::endl; */}
int getVal() const { return m_Val; }
private:
int m_Val;
};
int main()
{
sharedPtrVect myVect1, myVect2;
vectItr myVectItr;
std::shared_ptr<A> tmpPtr;
for(int i = 1 ; i <= 5 ; i++ ) {
std::cout << "Pushed back: " << i << std::endl;
tmpPtr = std::make_shared<A>(i);
myVect1.push_back(tmpPtr);
}
myVectItr = myVect1.begin();
for( ; myVectItr != myVect1.end() ; ++myVectItr) {
std::cout << "-----------------------------" << std::endl;
std::cout << "Element number: " << (*myVectItr).get()->getVal() << std::endl;
std::cout << "Element use count: " << (*myVectItr).use_count() << std::endl;
std::cout << "-----------------------------" << std::endl;
}
return 0;
}
The output of the above code is:
Pushed back: 1
Pushed back: 2
Pushed back: 3
Pushed back: 4
Pushed back: 5
-----------------------------
Element number: 1
Element use count: 1
-----------------------------
-----------------------------
Element number: 2
Element use count: 1
-----------------------------
-----------------------------
Element number: 3
Element use count: 1
-----------------------------
-----------------------------
Element number: 4
Element use count: 1
-----------------------------
-----------------------------
Element number: 5
Element use count: 2 //I am not sure why or how this is 2?
-----------------------------
I don't understand how the use_count() for the last vector element is 2. Shouldn't it be 1 like others? I am not creating any copies of the shared pointer stored in the last element of the vector.
What am I missing here?
EDIT: I have good experience in C++98, but less experience in C++11.
Shouldn't it be 1 like others? I am not creating any copies of the shared pointer stored in the last element of the vector. What am I missing here?
But you are creating a copy. You push_back() from tmpPtr. push_back() puts a copy of its argument into the vector, unless you tell it to move instead. (More on that later!)
Therefore, what happens for all but the last element is this:
tmpPtr holds the only reference to the shared resource
You push_back() a copy, so the copy-constructor of shared_ptr increments the use count to 2
You then assign the next element to tmpPtr, releasing the reference to, and thereby decrementing the use count of, the previous element's resource.
But, of course, there is no subsequent assignment on the last iteration of the loop. So, at the point of printing, tmpPtr is still in scope, and it retains a reference to the last resource that was allocated. Hence the 1-higher refcount on the last element. This seems perfectly expected to me. ;)
To see the results you expected, you need to either destroy tmpPtr after you copy it but before you print, or simply avoid the copy from it in the first place. The former could be done by moving its declaration into the for loop, as SirGuy pointed out in the comments.
However, clearly, the latter is superior. How do we do that? Well, C++11 lets us move instead. So, you could emplace_back( std::move(tmpPtr) ), in which the move will cast to an rvalue and thus invoke the move-constructor of the vector element. This will cause tmpPtr to release its reference upon being moved into the vector, effectively ensuring the use count is always 1. This leaves tmpPtr (like any moved-from object) in a valid-but-unspecified state, i.e. useful only to be reassigned-to.
(Note: push_back() will achieve the same thing, but I generally prefer using emplace_back() wherever possible, as it's more efficient in other situations, so it's a better default.)
Of course, you can then combine both of these: declare tmpPtr within the scope of the for loop, and move from it. However... you don't even need tmpPtr at all! It does not appear to serve any useful purpose. So, you could just not use it, and instead directly emplace_back() the result of make_shared(). Because the return value thereof will be an rvalue, it will implicitly be moved into the vector; no cast by std::move is needed.
Used Versions: OMNeT++ 5.0 with iNET 3.4.0
I created some code, which gives me reliable results in ‘step-by-step’- or ‘animated’ simulation mode. The moment I change to ‘fast’ or ‘express’ mode, it gets buggy. The following simplified example will explain my problems:
void MyMacSlave::handleSelfMessage(cMessage *msg)
{
if (msg == CheckAck) {
std::cout << “CheckAck: “ << msg << std::endl;
}
if (msg == transmissionAnnouncement) {
std::cout << “transmissionAnncouncement: “ << msg << std::endl;
}
if (msg == transmissionEvent) {
std::cout << “transmissionEvent: “ << msg << std::endl;
}
delete msg;
}
There is a function, which is called for handling self-messages. Depending on what self-message I got, I need to run different if queries.
I get this correct output in step-by-step or animated mode:
CheckAck: (omnetpp::cMessage)CheckAck
transmissionAnncouncement: (omnetpp::cMessage)transmissionAnncouncement
transmissionEvent: (omnetpp::cMessage)transmissionEvent
And this is the strange output I get using fast or express mode:
CheckAck: (omnetpp::cMessage)CheckAck
transmissionAnncouncement: (omnetpp::cMessage)transmissionAnncouncement
transmissionAnncouncement: (omnetpp::cMessage)transmissionEvent
transmissionEvent: (omnetpp::cMessage)transmissionEvent
The third output line shows that the self-message is ‘transmissionEvent’, but the ‘if (msg == transmissionAnnouncement)’ is mistakenly considered as true as well.
As shown above I get different simulation results, depending on the simulation mode I am using. What is the reason for the different output? Why is there even a difference?
As Christoph and Rudi mentioned there was something wrong with the memory allocation. When a pointer is de-allocated and a new one is allocated on the same memory, there will be something wrong. The difference regarding the usage of different running modes is just a sign that there are errors to that effect.
In my case it was useful to check for message-kinds like:
if (msg->getKind() == checkAckAckType) {
instead of the method used in the originally question. I defined the message-kinds using simple enums.
vector<int> a = { 1,2,3,4,5,6,7 };
pair<vector<int>, vector<int>::iterator> pair_of_itr; //not working showing wrong directional error!
auto pair_of_itr = minmax_element(a.begin(), a.end());
cout << *pair_of_itr.first << " " << *pair_of_itr.second << endl; // working with auto but not with the PAIR of iterator.
//cout << pair_of_itr->first << " " << pair_of_itr->second << endl // not working
return 0;
here i have explained via comments. plz do refer comments.
a->b is the same as (*a).b. *a.b is the same as *(a.b). So they differ in whether a is dereferenced, or a.b is dereferenced.
In your case, auto pair_of_itr = std::minmax_element ... creates a std::pair of iterators, and it is the iterator you want to dereference. So that would be *pair_of_itr.first. *pair_of_itr is ill-formed because a std::pair is not itself a pointer or iterator.
The problem with pair<vector<int>, vector<int>::iterator> pair_of_itr; is simply that the first element of the pair is a std::vector, not a std::vector::iterator. So in that case neither pair_of_itr nor pair_of_itr.first can be dereferenced. *pair_of_itr.second would compile, because the second element is an iterator.
It's usually a good idea to add redundant parentheses, particularly if you needed to ask whether they were necessary. Other people also might not remember that *a.b means *(a.b), and the parentheses don't cost a lot.
I am very new to C++ programming and have stumbled across a behaviour that confuses me and makes my coding harder. I have searched for answer a bit and could not find anything - I have also scrolled through C++ reference pages and that did not help either (please don't crucify me if the answer is in there - the page isn't role model for explaining things). Maybe I am missing something really obvious.
Could someone explain, the following behaviour of std::unordered_map ?
std::unordered_map<std::string, std::string> test_map;
test_map["test_key_1"] = "test_value_1";
test_map["test_key_2"] = "test_value_2";
std::cout << "'test_key_1' value: " << test_map["test_key_1"] << std::endl; // This returns "test_value_1"
std::cout << "test_map size before erase: " << test_map.size() << std::endl; // This returns 2
test_map.erase("test_key_1");
std::cout << "test_map size after erase: " << test_map.size() << std::endl; // This returns 1
std::cout << "'test_key_1' value after erase: " << test_map["test_key_1"] << std::endl; // This returns empty string
std::cout << "'non_existing_key' value: " << test_map["non_existing_key"] << std::endl; // This returns empty string
test_map.rehash(test_map.size()); // I am doing this because vague hints from internet, code behaves
// same way without it.
for (std::unordered_map<std::string, std::string>::iterator it = test_map.begin();
it != test_map.end(); ++it)
{
std::cout << "Key: " << it->first << std::endl;
}
// Above loop return both 'test_key_1' and 'test_key_2'.
// WHY!?
Why iterator is returning items that were already erased ? How can I make iterator return only items that are present in map ?
I will be grateful for any help, as I am really lost.
You are using operator[] to access previously erased elements which
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
If you need just to search for given key, use find method that returns map.end() if element was not found.
I'm trying to write a custom 'driver' for a keyboard (HID, if it matters), under Windows 7. The final goal is having two keyboards connected to the computer, but mapping all of the keys of one of them to special (custom) functions.
My idea is to use libusb-win32 as the 2nd keyboard's driver, and write a small program to read data from the keyboard and act upon it. I've successfully installed the driver, and the device is recognized from my program, but all transfers timeout, even though I'm pressing keys.
here's my code:
struct usb_bus *busses;
struct usb_device *dev;
char buf[1024];
usb_init();
usb_find_busses();
usb_find_devices();
busses = usb_get_busses();
dev = busses->devices;
cout << dev->descriptor.idVendor << '\n' << dev->descriptor.idProduct << '\n';
usb_dev_handle *h = usb_open(dev);
cout << usb_set_configuration(h, 1) << '\n';
cout << usb_claim_interface(h, 0) << '\n';
cout << usb_interrupt_read(h, 129, buf, 1024, 5000) << '\n';
cout << usb_strerror();
cout << usb_release_interface(h, 0) << '\n';
cout << usb_close(h) << '\n';
and it returns:
1133
49941
0
0
-116
libusb0-dll:err [_usb_reap_async] timeout error
0
0
(I'm pressing lots of keys in those 5 seconds)
There's only one bus, one device, one configuration, one interface and one endpoint.
The endpoint has bmAttributes = 3 which implies I should use interrupt transfers (right?)
so why am I not getting anything? Am I misusing libusb? Do you know a way to do this without libusb?
It's pretty simple actually - when reading from the USB device, you must read exactly the right amount of bytes. You know what that amount is by reading wMaxPacketSize.
Apparently a read request with any other size simply results in a timeout.