This was a question asked to me in an interview...
Is it possible to change the vtable memory locations after it's
created via constructor? If yes, is it a good idea? And how to do that?
If not, why not?
As i don't have that in depth idea about C++, my guess is that, it's not possible to change vtable after it's created!
Can anyone explain?
The C++ standards do not tell us how dynamic dispatch must be implemented. But vtable is the most common way.
Generally, the first 8 bytes of the object is used to store the pointer to vtable, but only if the object has at least 1 virtual function (otherwise we can save this 8 bytes for something else). And it is not possible to change the records in the vtable during run-time.
But you have memset or memcpy like functions and can do whatever you want (change the vtable pointer).
Code sample:
#include <bits/stdc++.h>
class A {
public:
virtual void f() {
std::cout << "A::f()" << std::endl;
}
virtual void g() {
std::cout << "A::g()" << std::endl;
}
};
class B {
public:
virtual void f() {
std::cout << "B::f()" << std::endl;
}
virtual void g() {
std::cout << "B::g()" << std::endl;
}
};
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
A * p_a = new A();
B * p_b = new B();
p_a->f();
p_a->g();
p_b->f();
p_b->g();
size_t * vptr_a = reinterpret_cast<size_t *>(p_a);
size_t * vptr_b = reinterpret_cast<size_t *>(p_b);
std::swap(*vptr_a, *vptr_b);
p_a->f();
p_a->g();
p_b->f();
p_b->g();
return 0;
}
Output:
A::f()
A::g()
B::f()
B::g()
B::f()
B::g()
A::f()
A::g()
https://ideone.com/CEkkmN
Of course all these manipulations is the way to shoot yourself in the foot.
The proper response to that question is simple: This question can't be answered. The question talks about the "vtable memory locations" and then continues with "after it's created via constructor". This sentence doesn't make sense because "locations" is plural while "it" can only refer to a singular.
Now, if you have a question concerning the typical C++ implementations that use a vtable pointer, please feel free to ask. I'd also consider reading The Design and Evolution of C++, which contains a bunch of background infos for people that want to understand how C++ works and why.
Related
I just wondering if the following way of delivering a pointer variable, created inside of the func1, to the caller (func2) is a correct way of doing this. If this is correct, will it release the memory when func2 is returned? If it is a bad idea, why is that?
int & func1()
{
std::shared_ptr<int> d = std::make_shared<int>(50);
return *d;
}
void func2(){
int & dd = func1();
}
This is a simplified code. I am assuming the size of d is huge(e.g images).
Added:
I realized that the following also works. What will be the pros and cons of each approach?
std::shared_ptr<int> & func1()
{
std::shared_ptr<int> d = std::make_shared<int>(50);
return d;
}
void func2()
{
std::shared_ptr<int> & dd = func1();
}
Both of those examples are bad. You can't use the return values of either func1, they are always dangling references.
int & func1()
{
std::shared_ptr<int> d = std::make_shared<int>(50);
return *d;
} // d is the only owner when it is destroyed, *d is also deleted
std::shared_ptr<int> & func1()
{
std::shared_ptr<int> d = std::make_shared<int>(50);
return d;
} // d is destroyed here
I am assuming the size of d is huge
You are mistaken. The size of the object pointed-to by d has no bearing on the size of d, just like with raw pointers.
E.g.
#include <iostream>
#include <memory>
struct Huge
{
int data[100000];
};
int main()
{
std::cout << sizeof(int) << std::endl
<< sizeof(int*) << std::endl
<< sizeof(std::shared_ptr<int>) << std::endl
<< sizeof(std::unique_ptr<int>) << std::endl
<< sizeof(Huge) << std::endl
<< sizeof(Huge*) << std::endl
<< sizeof(std::shared_ptr<Huge>) << std::endl
<< sizeof(std::unique_ptr<Huge>) << std::endl;
}
for me results in
4
8
16
8
400000
8
16
8
I realized that the following also works
If by works, you mean "is accepted by a C++ compiler", then yes. They both result in undefined behaviour if you use the references returned, so I would say they categorically don't work.
I wanted to make a simple comment out of this, but there was too much to be said. This is meant to be a precision of mathematician1975's comment, which in my opinion is a good point to bring up.
I thought just returning shared_ptr will require extra cost to copy the control block.
You may want to have a look at (N)RVO/copy elision, which is precisely the mechanism avoiding this kind of thing: https://en.cppreference.com/w/cpp/language/copy_elision.
Long story short: returning it won't copy it, but instead will build it in-place at caller's site. No performance cost!
I've made a basic live example which shows how (N)RVO works, available here: http://coliru.stacked-crooked.com/a/8a32afc3775c685e
EDIT: If it can help clarifying the process of all this, I've written an article about copy elision and [N]RVO.
From this question, I implement like this
Utils.h:
template<class T>
void SafeDeleteWithoutClass(T* &pVal) {
std::cout << __FUNCTION__ << std::endl;
delete pVal;
pVal = nullptr;
}
template<class T>
void SafeDeleteArrayWithoutClass(T* &pVal) {
std::cout << __FUNCTION__ << std::endl;
delete[] pVal;
pVal = nullptr;
}
main.cpp
#include "Utils.h"
struct Foo {
Foo() {std::cout << __FUNCTION__ << std::endl;}
~Foo() {std::cout << __FUNCTION__ << std::endl;}
}
int main()
{
Foo *pObj = new Foo();
SafeDeleteWithoutClass<Foo>(pObj2);
return 0;
}
It works well. But some guys in my team said it is not really better than macro. I don't know whether any example to prove this way is better than macro. Could you give me a hint?
It is not better then macro because you have no guarantee that it will save you from using pointer after deletion and deleting all things. It work practically the same. I guess that these guys just think it not better because it is the same. It is just written without using macro that's all.
Only advantage here is that you print some information on std::cout (but you can still do this in macro). And there are many disadventages here, to name few:
You can forget to call this function and have memory leak
Some one can still use pointer after it was deleted
It is hard to find if only one small object is leaking
You can call wrong function (e.g delete array for regular pointer)
Better to use std::shared_ptr<T> and std::unique_ptr. They will keep managing memory and make it clear who is the owner of memory (and memory ownership is important thing to consider on design of a class or whole project). But remember that smart pointers are not some miracle thing, you can still mess up some things. Take a look at this article to find out what not to do with them Top 10 dumb mistakes to avoid with C++ 11 smart pointers
I got some weird problem. I use delete operator inside of class method and I want to know how solve this problem.
This is code:
#include <iostream>
using namespace std;
class A
{
public:
int a;
~A() {
cout << "call ~A()" << endl;
}
void action()
{
/* code here */
delete this; //this line depends on some if statements
/* code here */
}
void test2() {
cout << "call test2()" << a << endl;
}
void test() {
a = 10;
cout << "call test()" << endl;
action();
//how can I check if data is deleted?
test2();
}
};
int main()
{
A* a = new A();
a->test();
}
How can I check if data is deleted by delete operator?
Is it even possible?
Using delete this; is nearly always "bad". There are exceptions, but those are really unusual. Think about what you are trying to do. Most of the time, this means that you should have a wrapper object and an inner object that is created/deleted by the wrapper object.
You can't check if something has been deleted (in a reliable way/portable way). In your particular test-case, you are exercising "undefined behaviour" by "using an object after it has been destroyed", which means you can't really tell what is going to happen. You have to trust the C++ runtime that delete does what it says on the label.
In C++ there are other return values available than void. Therefore your action can return something that indicates if this has been deleted or not.
Note that you should not access any non-static data members or call any non-static member functions after deleteing this. Some people feel it to be difficult to guarantee so they ban delete this altogether.
Note to opponents that C++ FAQ claims that delete this is legal construct and I haven't also found anything forbidding it.
I'm learning C++ using Eckel's "Thinking in C++". It states the following:
If a class contains virtual methods, a virtual function table is created for that class etc. The workings of the function table are explained roughly. (I know a vtable is not mandatory, but Visual C++ creates one.)
The calling object is passed to the called function as an argument. (This might not be true for Visual C++ (or any compiler).) I'm trying to find out how VC++ passes the calling object to the function.
To test both points in Visual C++, I've created the following class (using Visual Studio 2010, WinXP Home 32bit):
ByteExaminer.h:
#pragma once
class ByteExaminer
{
public:
short b[2];
ByteExaminer(void);
virtual void f() const;
virtual void g() const;
void bruteFG();
};
ByteExaminer.cpp:
#include "StdAfx.h"
#include "ByteExaminer.h"
using namespace std;
ByteExaminer::ByteExaminer(void)
{
b[0] = 25;
b[1] = 26;
}
void ByteExaminer::f(void) const
{
cout << "virtual f(); b[0]: " << hex << b[0] << endl;
}
void ByteExaminer::g(void) const
{
cout << "virtual g(); b[1]: " << hex << b[1] << endl;
}
void ByteExaminer::bruteFG(void)
{
int *mem = reinterpret_cast<int*>(this);
void (*fg[])(ByteExaminer*) = { (void (*)(ByteExaminer*))(*((int *)*mem)), (void (*)(ByteExaminer*))(*((int *)(*mem + 4))) };
fg[0](this);
fg[1](this);
}
The navigation through the vtable in bruteFG() works - when I call fg[0](this), f() is called. What does NOT work, however, is the passing of this to the function - meaning that this->b[0] is not printed correctly (garbage comes out instead. I'm actually lucky this doesn't produce a segfault).
So the actual output for
ByteExaminer be;
be.bruteFG();
is:
virtual f(); b[0]: 1307
virtual g(); b[1]: 0
So how should I proceed to get the correct result? How are the this pointers passed to functions in VC++?
(Nota bene: I'm NOT going to program this way seriously, ever. This is "for the lulz"; or for the learning experience. So don't try to convert me to proper C++ianity :))
Member functions in Visual Studio have a special calling convention, __thiscall, where this is passed in a special register. Which one, I don't recall, but MSDN will say. You will have to go down to assembler if you want to call a function pointer which is in a vtable.
Of course, your code exhibits massively undefined behaviour- it's only OK to alias an object using a char or unsigned char pointer, and definitely not an int pointer- even ignoring the whole vtable assumptions thing.
OK using DeadMG's hint I've found a way without using assembler:
1) Remove the ByteExaminer* arg from the functions in the fg[] array
2) Add a function void callfunc(void (*)()); to ByteExaminer:
void ByteExaminer::callfunc(void (*func)())
{
func();
}
... this apparently works because func() is the first thing to be used in callfunc, so ecx is apparently not changed before. But this is a dirty trick (as you can see in the code above, I'm always on the hunt for clean code). I'm still looking for better ways.
Here is a sample piece of code. Note that B is a subclass of A and both provide a unique print routine. Also notice in main that both bind calls are to &A::print, though in the latter case a reference to B is passed.
#include <iostream>
#include <tr1/functional>
struct A
{
virtual void print()
{
std::cerr << "A" << std::endl;
}
};
struct B : public A
{
virtual void print()
{
std::cerr << "B" << std::endl;
}
};
int main (int argc, char * const argv[])
{
typedef std::tr1::function<void ()> proc_t;
A a;
B b;
proc_t a_print = std::tr1::bind(&A::print, std::tr1::ref(a));
proc_t b_print = std::tr1::bind(&A::print, std::tr1::ref(b));
a_print();
b_print();
return 0;
}
Here is the output I see compiling with GCC 4.2:
A
B
I would consider this correct behavior, but I am at a loss to explain how it is working properly given that the std::tr1::functions were bound to &A::print in both cases. Can someone please enlighten me?
EDIT: Thanks for the answers. I am familiar with inheritance and polymorphic types. What I am interested in is what does &A::print mean? Is it an offset into a vtable, and that vtable changes based on the referred object (in this case, a or b?) From a more nuts-and-bolts perspective, how does this code behave correctly?
This works in the same manner as it would have worked with plain member function pointers. The following produces the same output:
int main ()
{
A a;
B b;
typedef void (A::*fp)();
fp p = &A::print;
(a.*p)(); // prints A
(b.*p)(); // prints B
}
It would have been surprising if boost/tr1/std::function did anything different since they presumably store these pointers to member functions under the hood. Oh, and of course no mention of these pointers is complete without a link to the Fast Delegates article.
Because print() is declared virtual, A is a polymorphic class. By binding to the print function pointer, you will be calling through an A pointer, much in the same way as:
A* ab = &b;
ab->print();
In the ->print call above, you would expect polymorphic behavior. Same it true in your code as well. And this is a Good Thing, if you ask me. At least, most of the time. :)