I need to copy the address of this pointer to a buffer and re-typecast it elsewhere. I am aware that I can do it, if I do it outside the class. But,here I specifically need to use some member function as given in the sample code provided here:
#include <iostream>
#include <cstring>
class MyClass
{
public:
MyClass(const int & i)
{
id = i;
}
~MyClass()
{
}
void getAddress(char* address)
{
memcpy(address, this, sizeof(this));
}
void print() const
{
std::cout<<" My id: "<<id<<std::endl;
}
private:
int id;
};
int main()
{
MyClass myClass(100);
std::cout<<"myClass: "<<&myClass<<std::endl;
myClass.print();
// Need to copy the address to a buffer, sepcifically using a function as follows and retrieve it later
char tmp[128];
myClass.getAddress(tmp);
// retreiving the pointer
MyClass* myClassPtr = (MyClass*) tmp;
std::cout<<"myClassPtr: "<<myClassPtr<<std::endl;
myClassPtr->print();
return 0;
}
My Output:
myClass: 0x7fff22d369e0
My id: 100
myClassPtr: 0x7fff22d369f0
My id: 100
As we can see two addresses are different. However, both function are printing the id correctly. I wonder how this happens! I also need the correct method.
Correct version of getAddress():
void getAddress(char* address)
{
const MyClass* tmp = this;
memcpy(address, &tmp, sizeof(this));
}
Update:
// retreiving the pointer
// MyClass* myClassPtr = (MyClass*) tmp; - wrong
MyClass* myClassPtr = *( (MyClass**) tmp );
You are not copying the value of the this pointer, but the data that the pointer is pointing to (memcpy expects the address of the data to copy).
The correct syntax would be:
MyClass* ptr = this;
memcpy(address, &ptr, sizeof(ptr));
That is why you get the same/correct output at the end.
Then, the assignment
MyClass* myClassPtr = (MyClass*) tmp;
is wrong too, you set the pointer to the same address as the char buffer, not to the address that is stored in the char buffer.
A possible solution could look like this:
MyClass* myClassPtr;
memcpy( &myClassPtr, tmp, sizeof( MyClass*));
Finally: I'd like to know what exactly you want to do, that you want to implement something like this? Maybe this is the solution for this problem, but I have a strong feeling that this is the wrong solution for the real problem ...
Related
I know it is a fairly basic violation, but what is it?
class xyz
{
void function1()
{
cout<<"in class";
}
};
int main()
{
xyz s1 = new xyz(100);
xyz s2 = s1;
s2.function1();
delete s1;
return 0;
}
Something is wrong about the memory allocation using new. I believe but I can't seem to understand the fundamental behind it and the resolution.
You can't assign T* to T (pathological cases aside).
xyz * s1 = new xyz();
xyz * s2 = s1;
s2->function1();
delete s1;
return 0;
Better yet, don't use naked new and delete and use a smart pointer:
auto s1 = make_unique<xyz>();
xyz * s2 = s1.get(); // non-owning pointer
s2->function1();
// no explicit delete necessary
new returns a pointer (xyz *) to an object, not an object, so you should correct the type of s1:
xyz* s1=new xyz(100);
and to call the method through the pointer you should use operator ->:
s1->function1();
which is the equivalent of dereferencing the pointer and calling the method on the object:
(*s1).function1();
I want to copy data to a struct member given a double pointer to that structure.
I cannot change the signature of copyFoo().
The member cnt is assigned the return value of GetCnt() as expected, but memcpy creates access violations when I use it like this.
Could someone elaborate how memcpy is to be used when I have a double pointer to a struct and a void pointer member? Thank you very much!
struct mystruct
{
void * data;
unsigned int cnt;
};
void copyFoo( myObj * inBar, mystruct **outFoo)
{
memcpy((*outFoo)->data, inBar->GetData(), inBar->GetLength() );
(*outFoo)->cnt= inBar->GetCnt();
}
int main(void){
myObj *in = getObj();
mystruct *out= new mystruct;
copyFoo(in, &out));
delete in;
delete out;
}
memberfunction GetData() of inbar returns a void pointer, GetCnt() returns unsigned int and GetLength() returns an int.
A memory block with appropriate size should be allocated before you try to copy the data into it:
void copyFoo(myObj *inBar, mystruct **outFoo)
{
(*outFoo)->data = malloc(inBar->GetLength()); // <-- THIS
memcpy((*outFoo)->data, inBar->GetData(), inBar->GetLength());
(*outFoo)->cnt= inBar->GetCnt();
}
in case the data member of mystruct is not yet initialized or points to the memory, which has already been freed, the copyFoo function invokes the undefined behavior.
I'm having problems with valid pointers in C++. I'm using one object in different threads, so I can't just set the pointer to NULL and return. Here's what I'm trying:
int main()
{
char *ptr = new char[1024]; //assume PTR = 0x12345678
changePtr(ptr); //after calling this,
//ptr is not NULL here.
return 0;
}
void changePtr(char *ptr)
{
delete [] ptr; //ptr = 0x12345678
ptr = NULL; //ptr = NULL
}
How can I change ptr to NULL for both functions?
change the signature of changePtr to:
void changePtr(char **ptr)
{
delete [] *ptr; //ptr = 0x12345678
*ptr = NULL; //ptr = NULL
}
And call it using:
changePtr(&ptr);
In C++, use reference parameter:
void changePtr(char *&ptr) {
delete [] ptr; //ptr = 0x12345678
ptr = NULL; //ptr = NULL
}
In C, you need to pass pointer to pointer, which is basically same thing with less pretty syntax.
You do not need to change the calling code. But you must give a modifiable variable as argument when calling, can't give for example NULL or nullptr, same as you can't do &NULL.
If you really want to manage memory in such a complex, error-prone way, then pass a reference to, rather than a copy of, the caller's pointer:
void changePtr(char *&ptr)
// ^
Much better would be to use a smart pointer; they are designed so that it's very difficult to leave them dangling when the target is deleted:
int main()
{
std::unique_ptr<char[]> ptr(new char[1024]); //assume PTR = 0x12345678
changePtr(ptr); //after calling this,
//ptr is empty here.
return 0;
}
void changePtr(std::unique_ptr<char[]> & ptr)
{
ptr.reset();
}
although if I wanted a dynamic array, I'd avoid new altogether and use std::vector.
I have seen a great many questions about how to check a pointer for validity. A large number of these questions have been about Windows. There may not be a general way to check in C++, but for a Windows specific solution the following seems to work on my system:
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv)
{
MEMORY_BASIC_INFORMATION lpBuffer;
int cActualBytes;
cActualBytes = VirtualQuery(&main, &lpBuffer, sizeof(lpBuffer)); // Can we get info about main?
if (!cActualBytes)
{
printf("Nope, you can't do that \n");
return 2;
}
if (cActualBytes != sizeof(lpBuffer))
{
printf("Surprise! Expected %d bytes, got %d\n", sizeof(lpBuffer), cActualBytes);
}
printf("Information for main\n");
printf("---------------------------\n");
printf("C reports pointer %p, Virtual Alloc sees it as %p\n",&main,lpBuffer.BaseAddress);
return 0;
}
What is the difference between the two copy functions below? I do not seem to see a difference between them. Specifically the void*& vs the void*.
So what is the difference between T*& and T*? When would I use one over the other? Also, if I made them accept const parameters, what would happen? What would the difference be?
#include <iostream>
void Copy(void* Source, void* Destination, int Size)
{
//memcpy(Destination, Source, Size);
char* S = static_cast<char*>(Source);
char* D = static_cast<char*>(Destination);
*D = *S;
}
void Copy2(void* &Source, void* &Destination, int Size)
{
char* S = static_cast<char*>(Source);
char* D = static_cast<char*>(Destination);
*D = *S;
}
int main()
{
int A = 2;
int B = 5;
int C = 7;
void* pA = &A;
void* pB = &B;
void* pC = &C;
Copy(pA, pB, 1);
Copy2(pA, pC, 1);
std::cout<< B <<std::endl;
std::cout<< C <<std::endl;
}
Both of the above print "2". Both are the same no?
One is a pointer, the other is a reference to a pointer.
Google both and pick up a C++ basics book.
Think of passing by pointer as passing a memory address by value (ie, a copy). In the receiving function, you have a copy of the memory address and you can change where that memory address pointer points to, and what that destination memory contents looks like. When you return from that function, the destination memory is still changed, but the original pointer is unchanged.
In contrast, a reference to a pointer allows you to change where that memory points to after you return from the function. Otherwise it is the same.
A common usage is a funciton which allocates memory such as:
SomeClass *someClass = null;
PopulateSomeClass(someClass);
...
void PopulateSomeClass(SomeCLass* &someCLass)
{
someClass = new SomeClass;
}
But really, google this for more detail - this is a more basic C++ concept.
For instance, a reference is typically implemented as a const * under the covers in the compiler. So it is a const pointer to pointer.
void func(char* buf) { buf++;}
Should I call it passing by pointer or just passing by value(with the value being pointer type)? Would the original pointer passed in be altered in this case?
This is passing by value.
void func( char * b )
{
b = new char[4];
}
int main()
{
char* buf = 0;
func( buf );
delete buf;
return 0;
}
buf will still be 0 after the call to func and the newed memory will leak.
When you pass a pointer by value you can alter what the pointer points to not the pointer itself.
The right way to do the above stuff would be
ALTERNATIVE 1
void func( char *& b )
{
b = new char[4];
}
int main()
{
char* buf = 0;
func( buf );
delete buf;
return 0;
}
Notice the pointer is passed by reference and not value.
ALTERNATIVE 2
Another alternative is to pass a pointer to a pointer like
void func( char ** b )
{
*b = new char[4];
}
int main()
{
char* buf = 0;
func( &buf );
delete buf;
return 0;
}
Please note I am not in any way advocating the use of naked pointers and manual memory management like above but merely illustrating passing pointer. The C++ way would be to use a std::string or std::vector<char> instead.
The pointer will not be altered. Pass by pointer means pass an address. If you want the pointer altered, you have to pass a double pointer a deference it once.
foo( char **b)
{
*b = NULL;
}
The pointer itself is being passed by value (the memory being pointed at is being passed by pointer). Changing the parameter inside the function will not affect the pointer that was passed in.
To implement reference semantics via "passing a pointer", two things must happen: The caller must take the "address-of" the thing to be passed, and the callee must dereference a pointer.
Parts of this can be obscured by the use of arrays, which decay to a pointer to the first element - in that sense, the array content is always "passed by reference". You can use an "array-of-one" to obscure the dereferencing, though.
This is the straight-forward apporoach:
void increment_me(int * n) { ++*n; } // note the dereference
int main() { int n; increment_me(&n); } // note the address-of
Here's the same in disguise:
void increment_me(int n[]) { ++n[0]; } // no visible *
int main() { int n[1]; increment_me(n); } // or &