I'm making some tests around c++ memory allocation.
In the following code sample I want to change the value of a const variable (= cannotBeChangedDirectly) using the memory location.
Why is it not working?
When I take a look at the memory I can see, that the value of the address (to which both variables, the const and the normal one are reffering to changes but when I print the result then the const variable still has the old result, why?)
Consider the following code sample:
#include "stdafx.h"
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
const int cannotBeChangedDirectly = 10;
std::cout << "cannotBeChangedDirectly &" << &cannotBeChangedDirectly << " cannotBeChangedDirectly =" << cannotBeChangedDirectly << std::endl;
int* canBeChanged = const_cast<int*>(&cannotBeChangedDirectly);
std::cout << "cannotBeChangedDirectly &" << &cannotBeChangedDirectly << " canBeChanged & " << canBeChanged << std::endl;
std::cout << "cannotBeChangedDirectly =" << cannotBeChangedDirectly << " canBeChanged = " << *canBeChanged << std::endl;
*canBeChanged = 19;
std::cout << "cannotBeChangedDirectly &" << &cannotBeChangedDirectly << " canBeChanged & " << canBeChanged << std::endl;
std::cout << "cannotBeChangedDirectly =" << cannotBeChangedDirectly << " canBeChanged = " << *canBeChanged << std::endl;
}
Changing const´s is undefined behaviour, because:
const is not only that the compiler won´t let you change the variable directly,
but it allows further compiler optimization, like allocating no variable at all
and insert the value everyhere
cannotBeChangedDirectly is const doesn't only mean you can't modify it directly, it means modifying it in anyway is undefined behavior, including modifying it through a pointer.
const_cast works only for memory which is not const in the first place.
void example(const std::string* s)
{
std::string* edits = const_cast<std::string*>(s);
*edits="bar";
}
std::string a;
const std::string b;
int main(){
example(&a); //ok
example(&b); //undefined behavior.
}
Related
#include <iostream>
#include <functional>
using Callback = std::function<void(const int)>;
int main() {
Callback testCall = [](const int &num) {
std::cout << "callback: " << num << " - " << &num << std::endl;
};
int num = 42;
testCall(num);
std::cout << "main: " << num << " - " << &num << std::endl;
}
Possible output:
callback: 42 - 000000B19197F618
main: 42 - 000000B19197F694
As you can see, even if i assign a lambda function which takes the parameter by reference it still uses a copy.
Is that correct?
If yes, why does it still compile? Why is there at least not a warning about the discrepancy between the Callback declaration parameters and the assigned lambda. (const int &num vs const int num)
When not usingconst it does not compile.
PS. if you find a better title, feel free to edit.
This is because testCall is a functor object that catch its parameter by copy and then call the lambda on it.
Try:
Callback f = [](const int &num) {
std::cout << "callback: " << num << " - " << &num << std::endl;
};
int main() {
int num = 999;
std::cout << "callback: " << num << " - " << &num << std::endl;
f(num);
[](const int &num) {
std::cout << "callback: " << num << " - " << &num << std::endl;
}(num);
}
you will see something like:
callback: 999 - 0x7ffeed60a9bc
callback: 999 - 0x7ffeed60a994
callback: 999 - 0x7ffeed60a9bc
which means that callBack is not the function by itself but an indirection to the function. And there is no problem regarding types...
Answer to this may helps you to understand what happens under the hood: How std::function works
I was going through the c++ website tutorials as a nice compliment to a college course I'm taking this semester (beginner). While learning about copy constructors and destructors, I came across this section of code:
// destructors
#include <iostream>
#include <string>
using namespace std;
class Example4 {
string* ptr;
public:
// constructors:
Example4() : ptr(new string) {}
Example4 (const string& str) : ptr(new string(str)) {}
// destructor:
~Example4 () {delete ptr;}
// access content:
const string& content() const {return *ptr;}
};
int main () {
Example4 foo;
Example4 bar ("Example");
cout << "bar's content: " << bar.content() << '\n';
return 0;
}
Now, I understand the destructor part, but the getter for the string member confused me. Why return a reference (alias) to the object (string in this case)?
// access content:
const string& content() const {return *ptr;}
What is the difference between that, and just returning the string?
string content() const {
return *ptr;
}
Is returning a const alias more efficient? Are you returning just the address of the string, or the string itself? What about when just returning the string, are you returning the entire string? Thanks.
Returning a string would be undesirable for two reasons:
It means an unnecessary copy of the string is performed, which is bad for performance
It also means that someone might attempt to modify the returned string, thinking that they modify the actual member of the class - const reference would not allow this, and trigger a compilation error.
the getter for the string member confused me. Why return a
reference (alias) to the object (string in this case)?
const string& content() const {return *ptr;}
What is the difference between that [return a reference],
and just returning the string?
string content() const { return *ptr;}
And you might ask if there is a difference between that
and returning only the pointer
const string* content() const { return ptr;}
I find no advantage of one over the other(s).
Well, maybe consider the scenario where the string contains 26 million chars, you probably want to avoid copying that.
But there is another issue (or maybe 2) you should be aware of, if only to evaluate what you have learned here.
On Lubuntu 18.04, using g++ (Ubuntu 7.3.0-27), a string s, with no data,
std::string s;
cout << sizeof(s) << " " << s.size() << endl;
Reports the numbers "32 0".
std::string s ("01234567890123456789");
cout << sizeof(s) << " " << s.size() << endl;
Reports values "32 20"
{
std::string s;
for (int i=0; i<1000000; i++)
{
for (char j='A'; j<='Z'; j++)
s.push_back(j);
}
cout << " " << sizeof(s) << " " << s.size() << endl;
}
This reports the values "32 26000000"
1 million alphabets
s is still only 32 bytes
From this, you may conclude a) that an instance of 'string' occupies 32 bytes regardless of data. b) because all the data resides elsewhere c) so some of the 32 bytes in a std::string instance is a pointer to where in dynamic memory the chars resides.
Hmmm.
If the obj instance is only 32 bytes, then you might ask why does Example4 use a pointer to place this SMALL object (the string instance) into the dynamic memory ... using 8 bytes to find 32, and then needing a second reference (of some pointer inside of the string instance) to reach the char's of Example4 string.
In the same way, a std::vector is 24 bytes (regardless of how many elements, and regardless of how big the elements). std::vector takes care of memory management, so that you don't have to.
Perhaps this lesson is meant to help you discover and evaluate what is in dynamic memory, and what is in automatic memory, to improve your choices.
The key idea, is that STL library containers handle dynamic memory for you, to greatly simplify your effort.
Or, perhaps the professor wants you to know more about the tools you are using. The standard containers, in some ways, isolate you from how this stuff works. Perhaps this assignment is to get a glimpse into what std::string does.
// here is some "g++ -std=c++17" code to single step through, illustrating several of the ideas
#include <iostream>
using std::cout, std::endl;
#include <sstream>
using std::stringstream;
#include <iomanip>
using std::setfill, std::setw;
#include <string>
using std::string;
#include <cstring>
using std::strlen;
class Example4
{
string* ptr;
public:
Example4() : ptr(new string) {}
Example4 (const string& str) : ptr(new string(str)) {}
~Example4 () {delete ptr;}
// access content:
const string& content() const {return *ptr;}
const string* contentP() const {return ptr;}
string show(string lbl)
{
stringstream ss;
ss << "\n " << lbl
<< " . 5 4 3 2 1"
<< "\n . '09876543210987654321098765432109876543210987654321'"
<< "\n " << "*ptr : '" << *ptr << "'"
<< "\n " << "(*ptr).size() : " << (*ptr).size()
<< "\n " << " ptr->size() : " << ptr->size()
<< "\n " << "strlen((*ptr).c_str()) : " << strlen((*ptr).c_str())
<< "\n " << "strlen(ptr->c_str()) : " << strlen(ptr->c_str())
<< "\n\n " << "sizeof(*ptr) : " << sizeof(*ptr)
<< " # 0x" << ptr << ',' // where ptr points to
<< "\n " << "sizeof (ptr) : " << sizeof(ptr)
<< "\n\n";
return ss.str();
}
};
class T996_t
{
public:
int operator()() { return exec(); }
private: // methods
int exec()
{
Example4 e4("Now is the time to answer all questions01234567890");
cout << "\n " << e4.show("Example4")
<< "\n '" << e4.content() << "'"
<< "\n '" << *e4.contentP() << "'\n\n"
<< endl;
{
std::string s;
cout << " " << sizeof(s) << " " << s.size() << endl;
}
{
std::string s("01234567890123456789");
cout << " " << sizeof(s) << " " << s.size() << endl;
}
{
std::string s;
for (int i=0; i<1000000; i++)
{
for (char j='A'; j<='Z'; j++)
s.push_back(j);
}
cout << " " << sizeof(s) << " " << s.size() << endl;
}
return 0;
}
}; // class T996_t
int main(int, char**) { return T996_t()(); }
This code compiles and runs on my Lubuntu. The compile command built by my make file starts with:
g++ -std=c++17 -m64 -ggdb
The test method on the following class does not have the effect I would expect it to. I have a suspicion it is something to do with the fact that the invocation of emplace_back somehow invalidates the reference obtained via the subscript.
Either way I would expect the second print in test to result in
v[0] = 1
however both result in
v[0] = 5
suggesting that the assignment does not take place.
class FooBar {
vector<size_t> v;
public:
size_t add(size_t x) {
cout << "add(" << x << ")" << endl;
size_t K(v.size());
v.emplace_back(x);
return K;
}
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
v[idx] = add(0);
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
};
int main(int argc, char* argv[])
{
FooBar f;
f.add(5);
f.test(0);
}
I know that I can get around the problem by creating a temporary to store the result of add and then perform the assignment but I am interested as to why I cannot use just a straight assignment and why I do not get any kind of error when attempting to perform this.
Compiled and tested with MSVC (Visual Studio 2015).
The line
v[idx] = add(0);
is cause for undefined behavior. You are modifying the contents of v in add while assuming that v[idx] will be valid.
For predictable behavior, you can use:
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
size_t val = add(0);
v[idx] = val;
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
I got this from an online exam (http://www.interqiew.com/tests?type=cpp) and have been stumped for some time.
I just don't get it. It compiles and runs fine. I've modified the code to be more expressive of the weirdness.
CODE:
#include <cstddef>
#include <iostream>
class A{
public:
A( ) : m_x( 3 ) { };
static ptrdiff_t member_offsetA(const A &a){
const char *p = reinterpret_cast<const char*>(&a);
const char *q = reinterpret_cast<const char*>(&a.m_x);
const char *z = reinterpret_cast<const char*>(&a.m_y);
const char *s = reinterpret_cast<const char*>(&a.m_s);
std::cout << q << " VS " << p << " VS " << z << " VS " << s << std::endl << std::endl;
return p-q;
}
static ptrdiff_t member_offsetB(const A &a){
const char *p = reinterpret_cast<const char*>(&a);
const char *q = reinterpret_cast<const char*>(&a.m_x);
const char *z = reinterpret_cast<const char*>(&a.m_y);
const char *s = reinterpret_cast<const char*>(&a.m_s);
std::cout << q << " VS " << p << " VS " << z << " VS " << s << std::endl << std::endl;
return z-s;
}
static ptrdiff_t member_offsetC(const A &a){
const char *p = reinterpret_cast<const char*>(&a);
const char *q = reinterpret_cast<const char*>(&a.m_x);
const char *z = reinterpret_cast<const char*>(&a.m_c);
std::cout << q << " VS " << q << std::endl << " VS " << z << std::endl;
return q-z;
}
private:
int m_x;
int m_c;
char m_y;
std::string m_s;
};
int main(){
A a;
std::cout << ( ( A::member_offsetA( a ) == 0 ) ? 0 : 1 ) << std::endl;
std::cout << ( ( A::member_offsetB( a ) == 0 ) ? 2 : 3 ) << std::endl;
std::cout << ( ( A::member_offsetC( a ) == 0 ) ? 4 : 5 ) << std::endl;
return 0;
}
OUTPUT: Symbols will be represented by unique letters preceded by three X's. So all XXXS's represent the same symbol. Whitespace means nothing was printed there.
XXXA VS XXXA VS VS XXXB
0
XXXA VS XXXA VS VS XXXB
3
XXXA VS XXXA
VS XXXF
5
How does any of this make sense?
Why would the casting for a class and a member int produce the same results? Wouldn't they be different? If they're the same, why would other member values be different?
Also, why would anyone ever use this?
P.S. Paste of actual output:
VS VS �# VS �����
0
VS VS �# VS �����
3
VS
VS �
5
I don't see anything strange here. It makes perfect sense.
For normal, non-polymorphic classes the address of an instance of a class will be the same as the address of the first member of that class. That's just what an instance of a class is; it's the sum of all its members laid out sequentially (the instance itself adds nothing, unless it's a polymorphic class, or has non-empty base classes.) This is (not exactly but almost) called an "standard-layout" class in C++ (Note: the actual definition is obviously more complex.)
In the case of the members inside a class (and in fact for all variables,) no two of them can have the same address. And in fact they need 1 or more bytes of memory (you know, to store the bits of their respective values inside them.) So it again makes perfect sense for the addresses for consecutive members be different.
You might want to check out this code (which I believe is more instructive):
(Note: beware that there is "undefined behavior" in my particular use of pointer arithmetic here, so this in not completely correct C++. But to my knowledge it works fine. It's here for demonstration purposes anyways, so don't use this in production!)
#include <cstddef>
#include <iostream>
#include <string>
template <typename T, typename U>
ptrdiff_t Dist (T const * from, U const * to) {
return reinterpret_cast<char const *>(to) - reinterpret_cast<char const *>(from);
}
class A{
public:
A( ) : m_x( 3 ) { };
void printOffsetsAndSizes () const {
std::cout << "A: " << reinterpret_cast<uintptr_t>(this) << " (" << sizeof(*this) << ")" << std::endl;
std::cout << " m_x: " << Dist(this, &m_x) << " (" << sizeof(m_x) << ")" << std::endl;
std::cout << " m_c: " << Dist(this, &m_c) << " (" << sizeof(m_c) << ")" << std::endl;
std::cout << " m_y: " << Dist(this, &m_y) << " (" << sizeof(m_y) << ")" << std::endl;
std::cout << " m_s: " << Dist(this, &m_s) << " (" << sizeof(m_s) << ")" << std::endl;
}
private:
int m_x;
int m_c;
char m_y;
std::string m_s;
};
int main () {
A a;
a.printOffsetsAndSizes ();
return 0;
}
which gives this output on Ideone:
A: 3213332880 (16)
m_x: 0 (4)
m_c: 4 (4)
m_y: 8 (1)
m_s: 12 (4)
I'm trying to store a lambda in an object system involving several layers of indirection. I'm using g++ 4.7.1.
Depending on how exactly I construct the (equivalent) objects, the lambda may or may not have the correct value.
Code:
#include <iostream>
#include <functional> // used for std::function
using namespace std; // TODO nope
typedef function<int()> intf;
struct SaveLambda {
const intf func;
SaveLambda(const intf& _func) : func(_func) {}
};
struct StoreSaved {
const SaveLambda* child;
StoreSaved(const SaveLambda& _child) : child(&_child) {
cout << "Before returning parent: " << child->func() << endl;
}
};
int main() {
const int ten = 10;
auto S = SaveLambda([ten](){return ten;});
cout << "No indirection: " << S.func() << endl << endl;
auto saved = StoreSaved(S);
cout << "Indirection, saved: " << saved.child->func() << endl << endl;
auto temps = StoreSaved ( SaveLambda([ten](){cout << "&ten: "<< &ten << endl; return ten;}) );
cout << "***** what. *****" << endl;
cout << "Indirection, unsaved: " << temps.child->func() << endl;
cout << "***** what. *****" << endl << endl;
cout << "ten still lives: " << ten << endl;
}
Compile as g++ -std=c++11 -Wall -o itest itest.cpp and run: notice the one line of output with a different value.
What am I doing wrong? I assumed that capture-by-value would, well, capture by value. (Observe most disconcertingly that the print in StoreSaved (line 15) produces the correct value, unlike line 34, despite these both referring to the same object. The only difference is adding another layer of indirection.)
This is wrong:
auto temps = StoreSaved(
/* This temporary value dies at the last semicolon! */
SaveLambda([ten](){cout << "&ten: "<< &ten << endl; return ten;})
);
StoreSaved then has a pointer to a nonexistent object. Using it is UB.
As already pointed out by others, the problem is that in temps you end with a pointer to a nonexistent SaveLambda struct, as it is a temporary.
You can keep a copy using a SaveLambda struct in StoreSaved, instead of a pointer:
struct StoreSaved {
const SaveLambda child;
StoreSaved(const SaveLambda& _child) : child(_child) {
cout << "Before returning parent: " << child.func() << endl;
}
};
You also have to change all the child->func() to child.func(), as you are not dealing with a pointer anymore.