Why is this variable messed up after a function call - c++

#include <iostream>
using namespace std;
template<class KeyT, class ValueT>
struct KeyValuePair {
const KeyT &key_;
const ValueT &value_;
KeyValuePair() {
cout << "KeyValuePair() constructor" << endl;
}
KeyValuePair( const KeyValuePair<KeyT, ValueT> &other) {
cout << "KeyvaluePiar copy constructor" << endl;
}
KeyValuePair(KeyT key, ValueT value) : key_(key), value_(value) {
cout << "KeyValuePair(KeyT, ValueT) constructor" << " key_: " << key_ << " value_ " << value_ << endl;
}
~KeyValuePair() {}
};
struct foo {
int i;
};
void dump(const KeyValuePair<int, foo*> &kp) {
//printf("dump printf key: %d, value: %p\n", kp.key_, kp.value_);
cout << "dump cout key_: " << kp.key_ << " value_: " << kp.value_ << " i: " << (kp.value_)->i << "\n";
}
int main() {
cout << "test kv\n";
foo *ptr = new foo();
ptr->i = 3000;
printf("address of ptr: %p\n", ptr);
dump(KeyValuePair<int, foo*>(10, ptr));
return 0;
}
Run it with
g++ -g -std=c++11 -fPIC -O0 -o main main.cc && ./main
on a Linux machine.
In the above c++ example code gives the following result
test kv
address of ptr: 0x18a1010
KeyValuePair(KeyT, ValueT) constructor key_: 10 value_ 0x18a1010
dump cout key_: 10 value_: 0x7fffae060070 i: -1375338428
It seems that KeyValuePair's value_ is messed up after calling dump function, anyone knows the reason? It seems to be related to reference and pointers.

Your member variable is a reference:
const KeyT &key_;
Your constructor, on the other hand, passes by value:
KeyValuePair(KeyT key, ValueT value)
That means you are storing a reference to a temporary variable that will get destroyed almost immediately.
One solution would be to pass by reference in your constructor:
KeyValuePair(KeyT& key, ValueT& value)
which is better, but not perfect, since you pass a int literal 10 into the function.
If you really just need a pair, the best solution is probably to use std::pair.

Related

Integer pointer only has correct value if I print it

I am implementing my own smart_pointer, which counts the references to the thing it points to. Here is my implementation so far:
#pragma once
#include <iostream>
template <typename T>
class smart_pointer{
T* pointer;
int* cnt;
public:
smart_pointer<T>(T *el): pointer(el) { int i = 1; cnt = &i; }; //
smart_pointer<T>(const smart_pointer<T>& other): pointer(other.pointer) {
// std::cout << ", *(other.cnt): " << *(other.cnt);
cnt = other.cnt;
(*cnt)++;
} // Copy-constructor
int counter(){
int c = *cnt;
return c;
}
};
In main.cpp, I did the following:
int main(){
// smart_pointer_examples();
std::string h("hello");
smart_pointer<std::string> p(&h);
std::cout << "p: " << p.counter();
smart_pointer<std::string> q(p);
std::cout << ", q: " << q.counter() << std::endl;
return 0;
}
The problem is that that outputs p: 1, q: 6487781. After a lot of time trying to find the issue by debugging and printing stuff, I found something that fixed my issue: By adding std::cout << ", *(other.cnt): " << *(other.cnt); somewhere in my copy-constructor, the output becomes p: 1, *(other.cnt): 1, q: 2, which is the desired behaviour. I can't for the life of me think of why printing the counter would change anything.
Edit: Also, if I only do *(other.cnt) without std::cout, the same problem that I started with happens.
You made a small mistake in implementing your idea.
I will not comment on the design of your smart pointer implementation.
The problem is that you implemented your counter as a pointer. That is wrong.
And, you are dereferencing a local variable. That is a semantic bug. The result is undefined. The value of the counter will be indeterminate. Additionally you should initialize your class members.
If we fix both, then your code will look like:
#pragma once
#include <iostream>
template <typename T>
class smart_pointer {
T* pointer{};
int cnt{};
public:
smart_pointer<T>(T* el) : pointer(el) { cnt = 1; }; //
smart_pointer<T>(const smart_pointer<T>& other) : pointer(other.pointer) {
// std::cout << ", *(other.cnt): " << *(other.cnt);
cnt = other.cnt;
cnt++;
} // Copy-constructor
int counter() const {
return cnt;
}
};
int main() {
// smart_pointer_examples();
std::string h("hello");
smart_pointer<std::string> p(&h);
std::cout << "p: " << p.counter();
smart_pointer<std::string> q(p);
std::cout << ", q: " << q.counter() << std::endl;
return 0;
}

Access map element via pointer in C++

I switched from c to c++ recently and just can't figure out what I'm doing wrong here.
I would like to access and set the member of a map via another function.
Here is my example which you can just copy to cpp.sh or so if you like
#include <iostream>
#include <map>
using namespace std;
struct test{
int i;
int j;
};
void addValues(test* val){
if (val == NULL){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
void printVal(test* val){
cout<<"finish " << val->i << " " << val->j;
}
int main()
{
map<string, test*> bla = {{"test1",NULL}};
addValues(bla.at("test1"));
printVal(bla.at("test1"));
return 0;
}
code from my project is a little bit more complex but it's basically this problem. I created a test in addValues() and have not deleted it. Why am I not able to print this value in printVal()? What am I missing?
Thanks in advance!
Parameters are passed by value. Pointers are no exception to that. Your addValues modifies a local copy of the pointer when a nullptr is passed. Modifying that local copy does not affect the pointer in the map. Pass the pointer by reference:
void addValues(test*& val){
if (val == nullptr){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
Or better yet, do not use raw pointers in the first place. Moreover, consider to write a constructor that initializes the members of test instead of relying on the caller to initialize them.
Example :
#include <iostream>
#include <map>
//using namespace std; NO teach yourself not to do this.
struct test
{
int i = 0; // <== in c++ you can initialize values of structs
int j = 0;
};
// this instead of printVal
std::ostream& operator<<(std::ostream& os, const test& t)
{
os << "i = " << t.i << ", j = " << t.j << "\n";
return os;
}
int main()
{
std::map<std::string, test> map =
{
{"test1",{1,1}},
{"test2",{2,2}},
};
// loop over all entries in the map
// range based for loop.
// each entry in the map is a key,value pair (not they key, not the value but a pair)
// https://en.cppreference.com/w/cpp/language/range-for
std::cout << "range based for over keyvalue pairs\n";
for (const auto& kv : map)
{
// note kv.second is where we use operator<< from earlier.
std::cout << "Key : " << kv.first << ", value : " << kv.second << "\n";
}
std::cout << "\n";
// structured bindings make code more readable
// https://en.cppreference.com/w/cpp/language/structured_binding
std::cout << "range based for using structured bindings \n";
for (const auto& [key, value] : map)
{
std::cout << "Key : " << key << ", value : " << value <<"\n";
}
std::cout << "\n";
return 0;
}

Avoid copy construction by std::transform

I'm calling std::transform with a lambda that takes by reference and gives back a reference to the vector element. However, according to my program output, the copy constructor is called and the objects are NOT the same.
Code:
#include <algorithm>
#include <iostream>
#include <vector>
class Math
{
private:
int val_ = 5;
public:
Math(const Math& m) {
std::cout << "Copy constructor, our address: " << this << ", his address: " << &m << std::endl;
}
Math(int val) : val_(val) {
std::cout << "Object constructed with " << val << std::endl;
}
};
int main()
{
std::vector<Math> v_math = { { 5 }, { 10 } };
std::transform(
begin(v_math),
end(v_math),
begin(v_math),
[](const Math& m)-> const Math& {
return m;
});
}
Output (Godbolt):
Object constructed with 5
Object constructed with 10
Copy constructor, our address: 0x23d7ec0, his address: 0x7fff9dc499a8
Copy constructor, our address: 0x23d7ec4, his address: 0x7fff9dc499ac
So three things are unclear to me right now:
Why are the objects different? Shouldn't they be the same?
Why is one object's address bigger than the other? Is this because the copied-to object remains on the stack which has offset-pointers?
How can I avoid copy construction as well (actually I just "misuse" std::transform for a declarative way of invoking a lambda on every std::vector element)?
The copies have nothing to do with your usage of std::transform. They happen when you construct your v_math std::vector, because you're using a std::initializer_list constructor, which forces copies during construction.
In your std::transform call, operator=(const Math&) is called, change your code to the following to see this.
class Math
{
private:
int val_ = 5;
public:
Math(const Math& m) {
std::cout << "Copy constructor, our address: " << this << ", his address: " << &m << std::endl;
}
Math(int val) : val_(val) {
std::cout << "Object constructed with " << val << std::endl;
}
Math& operator=(const Math& other) {
val_ = other.val_;
std::cout << "Operator=(const Math&) called!\n";
return *this;
}
};
int main()
{
std::vector<Math> v_math = { { 5 }, { 10 } };
std::cout << "After constructing v_math!\n";
std::transform(
begin(v_math),
end(v_math),
begin(v_math),
[](const Math& m)-> const Math& {
return m;
});
std::cout << "After std::transform call!\n";
}

How to use boost channels (and fibers) properly in a class?

I am trying to use boost channels and fibers in a class. Here is a simple test case which works fine but it is not exactly what I want. If I move "line:1" to "loc:1" the programs hangs (gdb shows at a spinlock inside boost::fibers after c->push(a)). Can anyone help me by pointing what am I doing wrong? Thanks.
Here is the sample code which works and produces the following,
#include <iostream>
#include <boost/fiber/all.hpp>
using namespace std;
template <class T>
class Block
{
private:
typedef boost::fibers::buffered_channel<T> channel_t;
typedef boost::fibers::fiber fiber_t;
fiber_t _thread_send;
fiber_t _thread_recv;
size_t _n;
channel_t* _chan;
public:
Block(size_t n) : _n(n), _chan(nullptr) {
// >>>>>>>>>> loc:1 <<<<<<<<<<<
}
virtual ~Block() {}
void _send(channel_t *c) {
cout << __func__ << endl;
int a = 1000;
cout << "Sending: " << a << endl;
c->push(a);
}
void _recv(channel_t *c) {
cout << __func__ << endl;
int a = 0;
c->pop(a);
cout << "Received: " << a << endl;
}
void do_work() {
cout << "do_work\n";
channel_t temp{_n}; _chan = &temp; // <<<<<<<<<<<< line:1
_thread_send = boost::fibers::fiber(bind(&Block::_send, this, _chan));
_thread_recv = boost::fibers::fiber(bind(&Block::_recv, this, _chan));
_thread_send.join();
_thread_recv.join();
}
};
int main()
{
Block<int> B(2);
B.do_work();
return 0;
}
Output:
do_work
_send
Sending: 1000
_recv
Received: 1000
Compiled using:
GNU/Linux 64 bit x86-64
g++ (GCC) 7.1.1 2017051
boost 1.64.0
g++ -c --std=c++14 -g -Wall -Wpedantic boost_channels.cpp -o boost_channels.o
g++ -lboost_context -lboost_fiber boost_channels.o -o boost_channels
channel_t temp{_n}; _chan = &temp; // <<<<<<<<<<<< line:1
in Block() will not work because temp goes out of scope after leaving Block()'s body and _chan would point to garbage/ freed memory
two versions are possible:
1) keep channel temp a local variable of do_work():
template <class T>
class Block
{
private:
typedef boost::fibers::buffered_channel<T> channel_t;
typedef boost::fibers::fiber fiber_t;
fiber_t _thread_send;
fiber_t _thread_recv;
size_t _n;
public:
Block(size_t n) : _n(n) {
}
virtual ~Block() {}
void _send(channel_t *c) {
cout << __func__ << endl;
int a = 1000;
cout << "Sending: " << a << endl;
c->push(a);
}
void _recv(channel_t *c) {
cout << __func__ << endl;
int a = 0;
c->pop(a);
cout << "Received: " << a << endl;
}
void do_work() {
cout << "do_work\n";
channel_t chan{_n};
_thread_send = boost::fibers::fiber(bind(&Block::_send, this, & chan));
_thread_recv = boost::fibers::fiber(bind(&Block::_recv, this, & chan));
_thread_send.join();
_thread_recv.join();
}
};
2) keep channel temp a member variable of Block<>:
template <class T>
class Block
{
private:
typedef boost::fibers::buffered_channel<T> channel_t;
typedef boost::fibers::fiber fiber_t;
fiber_t _thread_send;
fiber_t _thread_recv;
channel_t _chan;
public:
Block(size_t n) : _chan(n) {
}
virtual ~Block() {}
void _send(channel_t *c) {
cout << __func__ << endl;
int a = 1000;
cout << "Sending: " << a << endl;
c->push(a);
}
void _recv(channel_t *c) {
cout << __func__ << endl;
int a = 0;
c->pop(a);
cout << "Received: " << a << endl;
}
void do_work() {
cout << "do_work\n";
_thread_send = boost::fibers::fiber(bind(&Block::_send, this, & _chan));
_thread_recv = boost::fibers::fiber(bind(&Block::_recv, this, & _chan));
_thread_send.join();
_thread_recv.join();
}
};
both versions generate:
do_work
_send
Sending: 1000
_recv
Received: 1000
When you construct the channel in the Block constructor and take a pointer to it, the pointer _chan is pointing at garbage when temp goes out of scope. You could just make temp a member of Block or leave it where it works so in can be forwarded.
Update:
Brackets(braces) in C++ define scope
Block(size_t n) : _n(n), _chan(nullptr)
//the scope of the constructor starts at this brace
{
//temp gets instantiated
channel_t temp{_n};
//assign the pointer to the object
_chan = &temp;
} //put a break point here
Then use a memory watch to look at _chan. As you move past the closing bracket you should see the memory turn to garbage as temp gets destroyed. If you trace in at that point you will see temp meet its distributor.
I would just leave the temp in do_work.
Ok, declaring channel_t as a member works fine. I guess it is pointing to garbage. Also I learned that boost sync primitives does not like being std::move(ed).
Thanks guys for helping.

CLang LibTooling handling function Template arguments

I want to handle template arguments diffrently so for the code:
template <class T> class A {
public:
A() {}
};
void faa(A<int>& param);
I would like to know that param is a template specialisation and get access it's parameters.
So I wrote an ASTVisitor with function
bool VisitFunctionDecl(FunctionDecl *f) {
std::cout<< "VisitFunctionDecl" <<std::endl;
const DependentTemplateSpecializationType* t1;
const TemplateSpecializationType* t2;
for(ParmVarDecl* p :f->params())
{
t1=p->getType()->getAs<DependentTemplateSpecializationType>();
t2=p->getType()->getAs<TemplateSpecializationType>();
if(t1!=nullptr||t2!=nullptr)
{
std::cout<< "template param found" <<std::endl;
}
}
return true;
}
But those casts are both nullptr always - I never get the template param found output.
What am I doing wrong? Is there any other way to cast t to some king of type allowing checking of the template parameters?
Type of A<int>& is LValueReference (can be checked with getTypeClassName()). What you are probably trying to get is type pointed by reference. You can get it with getNonReferenceType() method.
bool VisitFunctionDecl(FunctionDecl *f) {
llvm::errs() << "VisitFunctionDecl:" << f->getQualifiedNameAsString()
<< "\n";
for (ParmVarDecl* p : f->params()) {
llvm::errs() << p->getType().getAsString() << " -> "
<< p->getType()->getTypeClassName() << "\n";
llvm::errs() << "isPointerType: "
<< p->getType()->hasPointerRepresentation() << "\n"
<< "isTemplateSpecialization: "
<< (nullptr != p->getType().getNonReferenceType()->getAs<
TemplateSpecializationType>()) << "\n";
}
return true;
}
output is:
VisitFunctionDecl:faa
const A<int> & -> LValueReference
isPointerType: 1
isTemplateSpecialization: 1