Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Shallow copy

11 views
Skip to first unread message

MC

unread,
Aug 7, 2010, 11:31:20 PM8/7/10
to
Hi I am writing a library in C++. In my library I want to implement a
feature that if an application programmer instantiates a class object
and later does a shallow copy by memcpy or by any other means. During
the run time when ever any function of the shallow copy object is
called it should print out a message Warning: Shallow Copy detected.

What will be the best way to do this?

Thanks.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Stefan van Kessel

unread,
Aug 8, 2010, 5:50:56 PM8/8/10
to
On 8/8/2010 5:31 AM, MC wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?
>
> Thanks.
>

One way of doing it, is keeping a copy of a this pointer.

#include <iostream>
class Foo
{
Foo* address_;
void detectShallowCopy(){
if(address_ != this)
std::cout<<"Warning: Shallow Copy"<<std::endl;
}
public:
Foo(){address_ = this;}
Foo(const Foo&)
{
address_ = this;
}
Foo& operator=(const Foo&)
{
address_ = this;
return *this;
}
void bar()
{
detectShallowCopy();
}
void baz()
{
detectShallowCopy();
}

};

int main()
{
Foo foo1;
foo1.bar();
Foo foo2(foo1);
foo2.bar();
foo2 = foo1;
foo2.baz();
std::cout<< "checkpoint" <<std::endl;
memcpy(&foo2, &foo1, sizeof(Foo));
foo2.bar();

// output:
// checkpoint
// Warning: Shallow Copy

Vaclav Haisman

unread,
Aug 9, 2010, 10:35:11 AM8/9/10
to
MC wrote, On 8.8.2010 5:31:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
I doubt the usefulness of any such "feature".

However, it could help storing some sort of self reference into the instance
to which you can later compare to. E.g.

struct S
{
S () : self (this) { }
S (S const & other) : self (this) { }
// etc.

void foo () { if (self != this) { /* bad copy detected */ }

S const * const self;
};

--
VH

Mathias Gaunard

unread,
Aug 9, 2010, 10:54:17 AM8/9/10
to
On Aug 8, 4:31 am, MC <manan.cho...@gmail.com> wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

You could store the address of the object into the object itself, and
everytime check if those are indeed the same.

marcin...@gmail.com

unread,
Aug 9, 2010, 10:55:39 AM8/9/10
to
On Aug 8, 5:31 am, MC <manan.cho...@gmail.com> wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?
>
> Thanks.
>
You could store object's address acquired from 'this' pointer
in constructor and check if the stored value is equal to 'this'
at begining of every method.

However IMO using memcpy or any of similar means to "shallow copy"
non-POD C++ object is such an fundamental error that you can ignore
it.
Someone who does such things will probably learn on his mistakes
soon enough.

Cheers
Sfider

Jens Schmidt

unread,
Aug 9, 2010, 10:52:54 AM8/9/10
to
MC wrote:

> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

Several ideas:
1. Don't do that. An application programmer who uses memcpy for non-POD
data is not a programmer. So it just doesn't happen.

2. #define memcpy to something that results in a compile error. Do that
for memmove too.

3. In the constructor and in the assignment operator, initialize a pointer
with this. Later you may check this equality.
--
Greetings,
Jens Schmidt

Kai-Uwe Bux

unread,
Aug 9, 2010, 10:56:21 AM8/9/10
to
MC wrote:

> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

I don't know about "best", but I would conjecture that it would be best to
design the program so that this feature would not be needed.

As for detecting shallow copies, what about something like this:

class detect_shallow_copy {

detect_shallow_copy * this_ptr;

public:

detect_shallow_copy ( void )
: this_ptr ( this )
{}

detect_shallow_copy ( detect_shallow_copy const & )
: this_ptr ( this )
{}

detect_shallow_copy &
operator= ( detect_shallow_copy const & ) {
return ( *this );
}

bool
is_shallow ( void ) const {
return ( this != this_ptr );
}

};

#include <cstring>
#include <iostream>

int main ( void ) {
detect_shallow_copy d;
detect_shallow_copy e;
std::memcpy( &e, &d, sizeof(d) );
std::cout << d.is_shallow() << "\n";
std::cout << e.is_shallow() << "\n";
}


Best

Kai-Uwe Bux

Francis Glassborow

unread,
Aug 9, 2010, 10:27:44 PM8/9/10
to
MC wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?
>
> Thanks.
>
The only way I can think of is to store the address of the object
internally something like:

class example {
example const * const my_address
// rest of class

}:

Now ensure that all the ctors set that address (and note that you will
have to write a copy ctor because the default copy ctor and copy
assignment cannot be instantiated). Now make all member functions check
that my_address == this.

However I think this is rather draconian, and I would much rather trust
the programmer not to shoot himself in the foot by applying memcpy to
copy a class instance. IIRC doing such a copy results in undefined
behaviour unless the class is a POD (I think that C++0x has introduced
more latitude to include other safe cases)

Chris Uzdavinis

unread,
Aug 9, 2010, 10:26:41 PM8/9/10
to
On Aug 7, 10:31 pm, MC <manan.cho...@gmail.com> wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

If you memcpy an object that is not POD, the result is undefined
behaviour. As such, there is no reliable way to make code detect it,
since you cannot trust what your program will actually do.

So, copies involving the copy constructor are the next area to detect/
prevent. The simplest way is to make the class's copy ctor private
and then nobody can use it. If you need to use it but want this
warning you describe, you might store the "this" pointer, and later
compare the current this to the stored one to detect a problem
whenver you want. Of course, copies should not copy the stored
pointer or the test would fail. I do not see much value in this,
however.

What are you trying to accomplish with this feature?

Chris

Dragan Milenkovic

unread,
Aug 10, 2010, 12:18:15 AM8/10/10
to
On 08/08/2010 05:31 AM, MC wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

Only plain structures should be memcpy-ed.

You simply design a class so that there is no shallow copy available.
Copy-ctor/assignment will either do deep copy or be removed.

Or maybe you wanted to detect your structures copied... But since
you mention "shallow copy", I'm guessing that this is not a structure
but encapsulates some complex meaning.

--
Dragan

Ulrich Eckhardt

unread,
Aug 10, 2010, 12:19:09 AM8/10/10
to
MC wrote:
> [...] I want to implement a feature that if an application

> programmer instantiates a class object and later does a shallow copy
> by memcpy or by any other means. During the run time when ever any
> function of the shallow copy object is called it should print out a
> message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

How about just preventing copying or assignment by making copy constructor
and assignment operator private? That would cover the correct ways to copy
a (non-trivial) C++ object.

Concerning memcpy(), I wouldn't bother. Anyone applying memcpy() to a class
object obviously has either no clue what they are doing or is a C++ expert
that knows precisely what they are doing.

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Nick Maclaren

unread,
Aug 10, 2010, 4:59:09 AM8/10/10
to
In article <a5817923-6f72-4b3b...@u26g2000yqu.googlegroups.com>,

marcin...@gmail.com <marcin...@gmail.com> wrote:
>
>However IMO using memcpy or any of similar means to "shallow copy"
>non-POD C++ object is such an fundamental error that you can ignore
>it.
>Someone who does such things will probably learn on his mistakes
>soon enough.

I wish :-( And I am afraid that Jens Schmidt is wrong, too; it does
happen, very commonly. I am not denying the fundamental nature of
the error, but the problem is that it 'works' in so many common cases.
The people who learn programming from copying incantations and hacking
them until the compiler shuts up often believe that it is allowed.
They then bleat about compiler bugs when it fails. And I am not
denying that they aren't programmers, either!

But there are a lot of them around ....


Regards,
Nick Maclaren.

Goran

unread,
Aug 10, 2010, 4:59:12 AM8/10/10
to
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?

Start by defining the term "shallow copy".

No, seriously. First, memcpy on anything but aggregate types (POD) in C
++ is an undefined behavior. Second, "shallowness" is a trait of the
type being copied, defined by the programmer who wrote the type.
There's no way for your code to know what is "shallow" for an
arbitrary type, simply because code can't read minds.

Even if you have some simplistic idea about a shallow copy, e.g.
"everything but members that are pointers", you still can't do it.
e.g. if you use your own memcpy, to "shallow copy" an object, how do
you plan to detect that? I mean,

TYPE v;
TYPE v2;
memcpy(v, v2, sizeof(v2)); // Warning: Shallow Copy detected?
Bwahahahha...

What you should instead do is to learn to handle memory. Learn "rule
of three" (wikipedia has a nice explanation). Learn auto_ptr, learn
shared_ptr, weak_ptr. When designing your code, learn to think in
terms of ownership (of objects). Stop barking up the wrong tree.

Goran.

cpp4ever

unread,
Aug 10, 2010, 4:19:20 PM8/10/10
to
On 08/08/2010 04:31 AM, MC wrote:
> Hi I am writing a library in C++. In my library I want to implement a
> feature that if an application programmer instantiates a class object
> and later does a shallow copy by memcpy or by any other means. During
> the run time when ever any function of the shallow copy object is
> called it should print out a message Warning: Shallow Copy detected.
>
> What will be the best way to do this?
>
> Thanks.
>

First and foremost you need to take great care. The Qt framework
implements this type of thing, calling it implicit sharing which
basically only allocates more memory when required. Underlying this
implementation is a number indicating the number of objects sharing the
memory. This leads to the address of the memory referenced by an object
can change seemingly unexpectedly, as I found out when using QVector
which then invalidated an iterator I was relying on. Hence Qt provides
mechanisms for checking if the object is attached to shared memory,
detaching the object from using shared memory, and ensuring the object
will not use shared memory. Finally you may want to consider whether
this library is going to be used in multi-threaded application.

HTH

cpp4ever

Vladimir Jovic

unread,
Aug 12, 2010, 3:08:52 AM8/12/10
to
Kai-Uwe Bux wrote:
> As for detecting shallow copies, what about something like this:
>
> class detect_shallow_copy {
>
> detect_shallow_copy * this_ptr;
>
> public:
>
> detect_shallow_copy ( void )
> : this_ptr ( this )
> {}
>
> detect_shallow_copy ( detect_shallow_copy const & )
> : this_ptr ( this )
> {}
>
> detect_shallow_copy &
> operator= ( detect_shallow_copy const & ) {
> return ( *this );
> }
>
> bool
> is_shallow ( void ) const {
> return ( this != this_ptr );
> }
>
> };
>
> #include <cstring>
> #include <iostream>
>
> int main ( void ) {
> detect_shallow_copy d;
> detect_shallow_copy e;
> std::memcpy( &e, &d, sizeof(d) );
> std::cout << d.is_shallow() << "\n";
> std::cout << e.is_shallow() << "\n";
> }
>

Very nice trick.
Does it depends on the compiler and how the hidden pointer *this is
implemented?
Will it work if detect_shallow_copy inherit from a class with virtual
destructor and methods?

tni

unread,
Aug 12, 2010, 2:18:22 PM8/12/10
to

Not really.

> Will it work if detect_shallow_copy inherit from a class with virtual
> destructor and methods?

Yes.

\\

memcpy is very dangerous in the presence of virtual stuff (and in C++98
formally only allowed for PODs).

Something like:

class A {
// has virtual stuff
...
};

A a1;
A a2;

memcpy(&a1, &a2, sizeof(a1));

will most likely work (but you are firmly in the area of undefined /
platform-specific behavior and the Compiler Vendor is not going to tell
you if it's supposed to work or not).

Something like:

class B : public A {
...
};

A a1;
B b1;
A& a2 = b1;

memcpy(&a1, &a2, sizeof(a1));

will most likely not work correctly.

Francis Glassborow

unread,
Aug 12, 2010, 3:46:33 PM8/12/10
to
It may look like a nice trick but it does nothing useful. It is not
enough to have a member function that can detect a shallow copy, EVERY
member function of the class(es) in question must check. Why? Because
any programmer who realises the need to check will be clever enough to
avoid the problem in the first place.

In addition we have the problem that once the shallow copy has been
created we need a way to destroy it and the normal dtor will not suffice.

Basically, IMO, the original question is predicated on the idea that you
might write a library for a programmer who is liable to break his own
code. If you want to do that there are hundreds of other things you
would need to detect and deal with. It is not the job of the library
designer to write for incompetent users; that is the job of education.

--
Note that robinton.demon.co.uk addresses are no longer valid.

0 new messages