Objective C has introduced a technology called ARC to free the developer from the burden of memory management. It sounds great, I think C++ developers would be very happy if g++ also has this feature.
ARC allows you to put the burden of memory management on the (Apple LLVM 3.0) compiler, and never think about retain, release and autorelease ever again
So, if LLVM3.0 can do that, I think g++ also can free C++ developers from the tough jobs of memory management, right?
Is there any difficulties to introduce ARC to C++?
What I mean is: If we don't use smart pointers, we just use new/new[], is it possible for a compiler to do something for us to prevent memory leaks? For example, change the new to a smart pointer automatically?
C++ has the concept of Resource Allocation is Initialization(RAII) & intelligent use of this method saves you from explicit resource management.
C++ already provides shared_ptr which provides reference counting.
Also, there are a host of other Smart pointers which employ RAII to make your life easier in C++.
This is a good question. ARC is much more than just an implementation of smart pointers. It is also different from garbage collection, in that it does give you full control over memory management.
In ARC you know exactly when objects are going to be released. The reason people think is isn't true, is that there's no explicit "release" call that you write. But you know when the compiler will insert one. And it's not in some garbage collection step, it's inline when objects are considered no longer needed.
It contains a compiler step that analyzes the code and tries to find any redundant sequences of incrementing and decrementing reference counts. This could probably be achieved by an optimizing C++ compiler if it was given a smart pointer implementation that its optimizer could see through.
ARC also relies on the semantics of objective c. Firstly, pointers are annotated to say whether they are strong or weak. This could also be done in C++, just by having two different pointer classes (or using smart and vanilla pointers). Secondly, it relies on naming conventions for objective c methods to know whether their return values should be implicitly weak or strong, which means it can work alongside non-ARC code (ARC needs to know if your non-ARC code intended to return an object with a +1 reference count, for example). If your "C ARC" didn't sit alongside non-"C ARC" code you wouldn't need this.
The last thing that ARC gives you, is really good analysis of your code to say where it thinks leaks may be, at compile time. This would be difficult to add to C++ code, but could be added into the C++ compiler.
There's no need. We have shared pointers that do this for us. In fact, we have a range of pointer types for a variety of different circumstances, but shared pointers mimic exactly what ARC is doing.
See:
std::shared_ptr<>
boost::shared_ptr<>
Recently I wrote some Objective-C++ code using Clang and was surprised to find that Objective-C pointers were actually handled as non-POD types in C++ that I could use in my C++ classes without issues.
They were actually freed automatically in my destructors!
I used this to store weak references in std::vectors because I couldn't think of a way to hold an NSArrary of weak references..
Anyways, it seems to me like Clang implements ARC in Objective-C by emulating C++ RAII and smart pointers in Objective-C. When you think about it, every NSObject* in ARC is just a smart pointer (intrusive_ptr from Boost) in C++.
The only difference I can see between ARC and smart pointers is that ARC is built into the language. They have the same semantics besides that.
One of the reasons C++ is used at all is full control over memory management. If you don't want that in a particular situation there are smart pointers to do the managing for you.
Managed memory solutions exist, but in the situation C++ is chosen rightfully (for large-scale big applications), it is not a viable option.
What's the advantage of using ARC rather than full garbage collection? There was a concrete proposal for garbage collection before the committee; in the end, it wasn't handled because of lack of time, but there seems to be a majority of the committee (if not truly a consensus) in favor of adding garbage collection to C++.
Globally, reference counting is a poor substitute for true garbage collection: it's expensive in terms of run time, and it needs special code to handle cycles. It's applicable in specific limited cases, however, and C++ offers it via std::shared_ptr, at the request of the programmer, when he knows it's applicable.
Take a look of Qt. Qt has implemented this feature by leverage the hierarchy chain. You can new a pointer and assign a parent to it, Qt will help you to manage the memory.
There are already some implementations of similar technologies for C++; e.g., Boehm-Demers-Weiser garbage collector.
C++11 has a special Application Binary Interface for anyone wishing to add her own garbage collection.
In the vast majority of cases, techniques like smart pointers can do the job of painless memory management for C++ developers.
Microsoft C++/CX has ARC for ref classes. Embarcadero has 2 C++ compilers, one of them has ARC.
Related
I have read about c++ pointers and their pitfalls, one of which is that one can access private data members of other class objects using pointer hacks as mentioned here and here.
Surely pointers in c++ gives a lot of flexibility to the language but what's the use of it if it can hamper the core OOP features of the language like data hiding ? Is this really a trade-off between security & flexibility ?
C++ is first and foremost a low level language that extends traditional C with fancier language constructs. With few exceptions, nothing was removed.
C++ is not just an OO language. It is functional, declarative, procedural, structural amd object oriented. It can even be used as a portable assembler, like C often is.
Pointers are a thin abstraction on top of how CPUs access memory. Having access to raw pointers in-language enables a huge amount of efficient code. Every systems programming language permits access to raw pointers; sometimes guarded by "unsafe" blocks; and C++ is also a systems programming language.
If you are coming at C++ from a single perspective, and wondering why it seems strangely shaped for your goals, try looking at it from another direction.
C++ was originally built on the C language. It added features without removing any. C had pointers and therefore C++ has pointers. Compatibility with the C interface remains an essential feature of C++. Therefore pointers will never be not-allowed.
Besides compatibility, pointers are very useful. Introducing object oriented programming to a system programming language being the initial reason for C++, it should be noted that indirection is essential for implementing runtime polymorphism. Sure, there is another method of indirection in C++ - references, but references are more limited and cannot be used to implement all algorithms that require the use of pointers.
Pointers are also required to implement node based data structures such as trees or linked lists.
c++ pointers and their pitfalls, one of which is that one can access private data members of other class objects using pointer hacks as mentioned here
That trick isnt so much enabled by the pointer but by the use of reinterpret_cast. It would be much more sensible to question why that language feature is allowed.
and here
Both this and the previous are cases where the language does not allow breaking of encapsulation. The problem isn't the pointer. The problem is that C++ - like C - has undefined behaviour (UB) when certain rules are violated.
You might be wondering, why does a language have UB. The answer is that if the rules were required to be checked at runtime to avoid UB, the program would necessarily be slower than it could be when we assume that the program didn't make a mistake. Since C and C++ are low level system programming languages, performance was chosen at the cost of protecting against bad programmers.
There is no trade-off involving security. That's because there is nothing to trade, since C++ does not offer security. The language offers tools (like data hiding) and compilers offer guardrails (most warnings) to help you do the right thing, but if you are determined to do the wrong thing in your program, you have the freedom to do so. Vive la résistance! Watch program crash override and acid burn.
Besides, if you want to access private members, there is a much simpler method that does not involve undefined behavior: edit the header files, and either change "private" to "public" or add your class/function as a friend. (I'm not sure if this affects ABI. You might need to recompile libraries. I did say "simpler" not "quicker".) No pointers involved.
There are so much literature about smart pointers, I have read as much as I could. I just want a simple answer.
I have used raw pointer for my 3D renderer engines, and now I have to share some widgets between renderers, so here smart pointer comes. Please guide me should I update my entire software/library with smart pointer (std::shared_ptr)? What will be the cons in that case? I know the pros, just wanna know are there any cons? and what things are important that I should consider during the transformation from raw pointers to smart pointers? please be specific? Thanks.
Generally, they are a useful tool but not all tasks are suitable for a single tool. That said, here's a few things you should consider:
Learning about smart pointers is a valuable skill. Knowing them is the base for applying them when appropriate and ignoring them in the few cases they are not.
Smart pointers are more than just std::shared_ptr. There is also std::unique_ptr, also look into std::make_shared, std::make_unique (C++14) and std::enable_shared_from_this as a minimum.
When passing std::shared_ptr as parameters, make sure you don't add synchronized, superfluous reference count manipulations, e.g., use const std::shared_ptr<...>&.
Even when the standardized smart pointers are not the right tool, know how they work and create your own RAII wrappers - still better than full-blown, error-prone raw pointers.
When interfacing existing C-style APIs, you can still often use smart pointers and only hand down the raw pointer to those APIs where needed, using .get() on the smart pointer.
Much is to say about the pros of smart pointers and as other have already said I would recommend using them, where appropriate, in your applications.
When it comes to the API of libraries, I would say: It depends. If you are distributing your library in source form, then yes, you might use smart pointers in your API and your users might benefit from them. If you however want to distribute your library as DLL, smart pointers are not the right tool. That's because they are defined as templates and template classes are not distributable as DLLs. The users of your library would be forced to use the exact same compiler and template library as you did for the production of the DLL -- and that might be not what you want. Hence, for APIs of DLLs I would think twice before using smart pointers.
I'm not very experienced with either C++ or iOS, so I'm just curious if iOS the reference counting works basically alike in boost shared pointers and in NSObject?
From what I gather here, using ARC is very similar to using std::shared_ptr ("strong" pointers) and std::weak_ptr ("weak" pointers).
Abuse the former, and avoid the latter. Anyway, prefer std::unique_ptr if you can.
(Also, I am somewhat astonished that you had to release pointers manually when programming for iOS. In the 21st century.)
I'm not very experienced with C++ so I may be not completely correct about shared_ptr, but for me they doesn't seem alike. In Obj-C there're two options. Manual memory management - you manually increment and decrement reference counts for your objects, no magic occurs here. And new ARC which is mostly compile-time feature, while shared_ptr is just runtime implementation.
I was exploring C++0x today, and I encountered the new lambda feature. My question is how are these different (in terms of use) from blocks and why might one prefer one over the other?
Thanks.
there is a a short syntax with C++0x lambdas to take every variable in
scope by reference. ([&]) The type of a lambda is also unspecified,
allowing potentially more optimal code.
Now, when you look at Apple blocks, it will require __block specifiers
added to variables you want to modify (the very fact that this is
required suggests the whole system is defective). Variables are taken
by reference but then by value when the block exits the scope (and the
copied context necessarily lives on the heap, it seems). A weird
semantic that will only lead to broken designs, but probably makes
people that love GC happy. Without saying this probably has quite the
efficiency cost, of course, since this requires special indirections.
It is claimed the C++0x lambdas syntax would break compatibility with
C programs, but I don't think that is true. There are probably other
problems to integrate it with C, though, mainly the fact that C can't
really deal with unspecified types and build type erasure.
Apple blocks is really just an ObjC feature they try to generalize to
other languages. For C++, the system designed for that language is
just so much better.
EDIT:
To properly give credit, I took this information from http://www.rhinocerus.net/forum/language-c-moderated/558214-blocks-vs-c-lambdas.html a long time ago. That link is dead now; however, the original discussion appears to be archived here, thanks to #stefan for finding it.
I think it basically comes down to a question of your starting point. If you're starting from Objective-C, and writing C++ (Objective-C++) primarily (or exclusively) as an adjunct to Objective-C, then using blocks throughout all the code may make sense, simply to retain as much commonality as possible across the code base. Even if (for example) a project used some pieces written in Objective-C and others in C++, it could make sense to use blocks in both retain as much similarity throughout the code base as possible.
Unless you're using them outside of C++, however, I see little reason to prefer blocks over C++ lambdas. In what I'd guess to be the most common use (a predicate or action in an algorithm) the only noticeable difference between the two would be that one starts with ^ and the other with [].
Older versions of Objective C++
Before the ARC, there were internal differences in the implementation of blocks and lambdas that were likely to affect some more advanced uses. For example, blocks worked vaguely like C strings, so you used Block_copy to copy one, Block_release to free the copy, and so on. On the other hand, in C++ this is all automated so the copy ctor automatically uses Block_copy and the dtor Block_release as needed. At the same time, it did involve a bit more "magic", so (for example) when you copy a block, the copy is always allocated dynamically, regardless of how the source was allocated.
If, for one reason or another, you're stuck with using an older (I'm tempted to say "ancient") compiler or maintaining older code (and don't want to update the codebase as a whole) the memory management difference may be worth taking into account.
Mike Ash provides a detailed comparison. Blocks and lambdas differ in their syntax, their data type, the way they capture variables, the way they behave when copied, and their performance.
How they relate to C/C++/Objective-C:
I will refer to Apple's blocks extension as "Objective-C blocks" even
though this is not entirely correct. They are actually an addition to
C (and can even be used in C++), with some extra behaviors to make
them more useful in Objective-C. However, they are deeply intertwined
with Objective-C in their implementation, and "C blocks" is vague, so
I think that "Objective-C blocks" is the best way to refer to them
here.
C++0x lambdas are part of C++ only and can't be used from C.
Presumably they can be used in Objective-C++ if the compiler supports
C++0x.
A very high-level summary of the differences:
Objective-C blocks are somewhat simpler to write and to use,
especially in the case of using them for asynchronous or background
tasks where the block has to be copied and kept alive beyond the
lifetime of the scope where it was created. C++0x lambdas ultimately
provide more flexibility and potential speed, but at the cost of
considerable added complexity.
As of recent clang versions (3.2, 3.3rc and 3.4svn) they are interchangable in Objective-C(++) code. In C++ you have to use lambda, but in Objective-C(++) if you have
C++ support in your libobjc.
Apple's libobjc.B.dylib have it for sure. If you are using GNUstep, you need to either compile libobjc2 (and only libobjc2) with cmake and linking against libsupc++ (or whatever C++ ABI library you use) or link your project against libobjcxx as well
Blocks runtime should exist.
It is part of libSystem.dylib on OS X which libc is linked against so it is not much an issue there. You can use LLVM compiler-rt for this or use libobjc2. I personally recommend you use libobjc2 as it provided a Blocks runtime that is compatible with the rest of GNUstep, which is also called for.
Foundation kit.
This is due to how clang handle the ABI of interchanging C++ lambda and Objective-C blocks. clang do so with NSAutoreleasePool which is part of Foundation.
then you can safely interchange parts.
We are using c++ to develop an application that runs in Windows CE 4 on an embedded system.
One of our constraint is that all the memory used by the application shall be allocated during startup only. We wrote a lot of containers and algorithms that are using only preallocated memory instead of allocating new one.
Do you think it is possible for us to use the boost libraries instead of our own containers in these conditions?
Any comments and/or advice are welcomed!
Thanks a lot,
Nic
We use boost for embedded systems. With boost you can pick and choose what you use. We use smart_ptr and boost::bind in all of our projects. We write software for cheap cell phones.
And if Windows CE can run on your hardware I would expect that parts of boost would be applicable.
There are parts of boost that have no allocation and you might find them useful.
I would pick and choose based on your requirements.
Like anything that you use, you need to know the costs.
You could write your own allocator for the container, which allocates from a fixed size static buffer. Depending on the usage patterns of the container the allocator could be as simple as incrementing a pointer (e.g. when you only insert stuff into the container once at app startup, and don't continuously add/remove elements.)
Replacing your containers with Boost containers is NOT a good idea. The work to make appropriate custom allocators wouldn't be that bad, but you'd be violating the spirit of your 'allocate at startup' rule. The idea behind this rule (in my experience) is generally to make sure that you don't have to deal with out of memory type situations at run-time. The idea is to make sure that you have all the memory you could possibly need RIGHT AT THE START, so that there's no possibility of any part of the system coming up short of memory later on.
If you used the Boost containers with a custom allocator, you'd suddenly have to deal with the possibility that the pool the container is allocating from could go empty, thus eliminating the purpose of the 'allocate at startup' rule.
In the situation of a limited memory device, I would avoid any kind of container more complex than a statically allocated array.
Boost is a set of libraries. Some of them are focussed on template metaprogramming. Those don't even use any memory at runtime. But your question seems to be about replacing your containers. I'd doubt that is possible except using custom allocators. But even then, it's most likely you would be using plain STL containers and not boost. Boost only provides the TR1 containers, for those compilers that do not yet include TR1.
Do not use Boost.
It is a big library and your basic memory allocation requirements are very different from those of the libraries designers.
Even if you can get a current version of Boost to work according to your requirements with custom allocators it may break with a new version of Boost.
Feel free to look at the Boost source code though for some useful ideas but use your own implementation for what you need.
I'm looking into this right now — I would like to use circular buffers, lock-free containers, and asynchronous I/O, and instead of allocating dynamic memory, I'd prefer to use memory pools.
The biggest problem I've seen so far is that shared_ptr is used in a lot of places, with no easy way to replace it with intrusive_ptr. Since shared_ptr allocates dynamic memory to keep track of the reference count, I can't use it in an embedded system.
Fixing this looks doable, but a lot of work — I have to expand the template specification of any class that contains a shared_ptr so that the specific type of shared-pointer can be changed to intrusive_ptr if desired. So now I have to consider how much work that'll be, versus how much work it'll be to write my own version of the Boost features I need. Not a pleasant place to be.
I hope someone points out why I'm wrong about this.