Understanding memory management in mingw/g++ - c++

I was given an assignment to basically explain this. I have taken a quick look at the compiler documentation, and it seems to be a good place to start although it is quite extensive and I don't have much time. I'd like to know if I'd need to understand the C99 standards beforehand, or if there's another good source I can check. I'm going to be using it with Windows if it makes any difference. I also understand simple concepts such as heaps, stacks, linking and whatnot.

AFAIK, g++ is simply a C/C++ compiler, nothing more. memory is managed according to the standard C/C++ libraries.

Any decent C/C++ tutorial should give the basics for this information - but memory management in C/C++ is a huge topic. Surely for an entry level class your instructor would give some guidance & probably a more specific, less open-ended question.

g++ is just a compiler. It follows the rules of the language it compiles (In G++'s case, C++, but you also mention C99).
And for your fairly specific questions, you may need to
Consult the language standard (For C++ this is ISO/IEC 14882 ). Unfortunately not free, but you can find drafts online for free that are basically as good as the real thing. The latest official version is C++2003 (ISO/IEC 14882-2003), but contains only very minor changes from the original '89. C++09 is getting close to completion too, and again, there are drafts available online for this. Be warned though, it is heavy reading, and I wouldn't recommend trying to find anything there unless you're already very familiar with the language.
Analyze the assembler code the
compiler generates. The standard
leaves a lot up to the
implementation, so the only way to
find out how G++ specifically pushes
things onto the stack, in which
order and so on, is to analyze the
code it generates. (Also note that
this likely changes between
different versions of G++)
C++ is a notoriously underspecified language. There are huge chunks that just aren't covered by the standard, and where the compiler is free to do what it likes. This makes it a bit of a challenge to find out exactly what a given compiler is doing under the hood.
For this reason, you should also make sure you know exactly what you're expected to do. Dig up information on what the language says about memory management, or how g++ specifically deals with it?

I'm not clear on this question. If by "understanding memory management in mingw/g++" you mean "understand how the mingw g++ compiler handles memory internally while it is compiling files, such as when it allocates and frees abstract syntax tree nodes, etc.") then your answer is that as a multi-pass compiler GCC may not know the optimal lifetime for any particular piece of data but it does know that large groups of objects won't be needed from one pass to the other, so it uses memory pools when possible and garbage collection elsewhere.
On the other hand, if you're asking about how "how/when/what order ... objects, functions, variables, etc are put into the stack ... what is allocated and when and how this impacts performance" then you're in for a long night skimming through code.

Related

C++0x lambda vs blocks

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.

How important is standards-compliance?

For a language like C++ the existence of a standard is a must. And good compilers try their best (well, most of the good compilers, at least) to comply. Many compilers have language extensions, some of which are allowed by the standard, some of which are not. Of the latter kind 2 examples:
gcc's typeof
microsoft's compilers allow a pure virtual function declaration to have both a pure-specifier(=0) and a definition (which is prohibited by the standard - let's not discuss why, that's another topic:)
(there are many other examples)
Both examples are useful in the following sense: example1 is a very useful feature which will be available in c++0x under a different name. example2 is also useful, and microsoft has decided not to respect the ban that made no sense.
And I am grateful that compilers provide language extensions that help us developers in our routine. But here's a question: shouldn't there be an option which, when set, mandates that the compiler be as standards compliant as it can, no matter whether they agree with the standard or not. For example visual studio has such an option, which is called disable language extensions. But hey, they still allow example2.
I want everyone to understand my question correctly. It is a GREAT thing that MSVC allows example2, and I would very much like that feature to be in the standard. It doesn't break any compliant code, it does nothing bad. It just isn't standard.
Would you like that microsoft disable example2 when disable language extensions is set to true? Note that the words microsoft, example2, etc. are placeholders :)
Why?
Again, just to make sure. The crucial point is: Should a compiler bother to provide a compliant version (optionally set in the settings)(in its limits, e.g. I am not talking about export) for a certain feature when they provide a better alternative that is not standard and is perhaps even a superset of the standard, thus not breaking anything.
Standards compliance is important for the fundamental reason that it makes your code easier to maintain. This manifests in a number of ways:
Porting from one version of a compiler to another. I once had to post a 1.2 million-LOC app from VC6 to VC9. VC6 was notorious for being horribly non-Compliant, even when it was new. It allowed non-compliant code even on the highest warning levels that the new compiler rejected at the lowest. If the code had been written in a more compliant way in the first place, this project wouldn't (shouldn't)have taken 3 months.
Porting from one platform to another. As you say, the current MS compilers have language extensions. Some of these are shared by compilers on other platforms, some are not. Even if they are shared, the behavior may be subtly different. Writing compliant code, rather that using these extensions, makes your code correct from the word go. "Porting" becomes simply pulling the tree down and doing a rebuild, rather than digging through the bowels of your app trying to figure out why 3 bits are wrong.
C++ is defined by the standard. The extensions used by compilers changes the language. New programmers coming online who know C++ but not the dialect your compiler uses will get up to speed more quickly if you write to Standard C++, rather than the dialect that your compiler supports.
First, a reply to several comments. The MS VC extension in question is like this:
struct extension {
virtual void func() = 0 { /* function body here */ }
};
The standard allows you to implement the pure virtual function, but not "in place" like this, so you have to write it something like this instead:
struct standard {
virtual void func() = 0;
};
void standard::func() { ; }
As to the original question, yes, I think it's a good idea for the compiler to have a mode in which it follows (and enforces) the standard as accurately as possible. While most compilers have that, the result isn't necessarily as accurate a representation of the standard as you/I would like.
At least IMO, about the only answer to this is for people who care about portability to have (and use) at least a couple of compilers on a regular basis. For C++, one of those should be based on the EDG front-end; I believe it has substantially better conformance than most of the others. If you're using Intel's compiler on a regular basis anyway, that's fine. Otherwise, I'd recommend getting a copy of Comeau C++; it's only $50, and it's the closest thing to a "reference" available. You can also use Comeau online, but if you use it on a regular basis, it's worth getting a copy of your own.
Not to sound like an EDG or Comeau shill or anything, but even if you don't care much about portability, I'd recommend getting a copy anyway -- it generally produces excellent error messages. Its clean, clear error messages (all by themselves) have saved enough time over the years to pay for the compiler several times over.
Edit: Looking at this again, some of the advice is looking pretty dated, especially the recommendation for EDG/Comeau. In the three years since I originally wrote this, Clang has progressed from purely experimental to being quite reasonable for production use. Likewise, the gcc maintainers have (IMO) made great strides in conformance as well.
During the same time, Comeau hasn't released a single new version of their compiler, and there's been a new release of the C++ standard. As a result, Comeau is now fairly out of date with respect to the current standard (and the situation seems to be getting worse, not better -- the committee has already approved a committee draft of a new standard that is likely to become C++14).
As such, although I recommended Comeau at that time, I'd have difficulty (at best) doing so today. Fortunately, most of the advantages it provided are now available in more mainstream compilers -- both Clang and gcc have improved compliance (substantially) as outlined above, and their error messages have improved considerably as well (Clang has placed a strong emphasis on better error messages, almost from its inception).
Bottom line: I'd still recommend having at least two compilers installed and available, but today I'd probably choose different compilers than I did when I originally wrote this answer.
"Not breaking anything" is such a slippery slope in the long run, that it's better to avoid it altogether. My company's main product outlived several generations of compilers (first written in 1991, with RW), and combing through compiler extensions and quiet standards violations whenever it was the time to migrate to a newer dev system took a lot of effort.
But as long as there's an option to turn off or at least warn about 'non-standard extension', I'm good with it.
34, 70, 6.
I would certainly want an option that disables language extensions to disable all language extensions. Why?
All options should do what they say they do.
Some people need to develop portable code, requiring a compiler that only accepts the standard form of the language.
"Better" is a subjective word. Language extensions are useful for some developers, but make things more difficult for others.
I think that it's critical that a compiler provide a standards-only mode if it wants to be the primary one used while developing. All compilers should, of course, compile standards compliant code, but it's not critical they they don't extend if they don't think of themselves as the primary compiler -- for example, a cross-compiler, or a compiler for a less popular platform that is nearly always ported to, rather than targeted.
Extensions are fine for any compiler, but it would be nice if I had to turn them on if I want them. By default, I'd prefer a standards-only compiler.
So, given that, I expect MSVC to be standards-only by default. The same with gcc++.
Stats: 40, 90, 15
I think standards compliance is very important.
I always consider source code is more for the human readers than for the machine(s). So, to communicate programmer's intention to the reader, abiding the standard is like speaking a language of lowest common denominator.
Both at home and work, I use g++, and I have aliased it with the following flags for strict standard compliance.
-Wall -Wextra -ansi -pedantic -std=c++98
Check out this page on Strict ANSI/ISO
I am not a standards expert, but this has served me well. I have written STL-style container libraries which run as-is on different platforms, e.g. 32-bit linux, 64-bit linux, 32-bit solaris, and 32-bit embedded OSE.
Consider indicators on cars (known as "turn signals" in some jurisdictions); they are a reliable way to determine which direction someone's going to turn off a roundabout... until just one person doesn't use them at all. Then the whole system breaks down.
It didn't "hurt anyone" or obviously "break anything" in IE when they allowed document.someId to be used as a shortcut for document.getElementById('someId').... however, it did spawn an entire generation of coders and even books that consequently thought it was okay and right, because "it works". Then, suddenly, the ten million resulting websites were entirely non-portable.
Standards are important for interoperability, and if you don't follow them then there's little point in having them at all.
Standards-compliance hounds may get hated for "pedanticism" but, really, until everybody follows suit you're going to have portability and compatibility problems for ever.
How important standards-compliance is depends on what you are trying to achieve.
If you are writing a program that will never be ported outside of its current environment (especially a program that you're not planning to develop/support for a long time) then it's not very important. Whatever works, works.
If you need your program to remain relevant for a long time, and be easily portable to different environments, than you will want it to be standards compliant, since that's the only way to (more or less) guarantee that it will work everywhere.
The trick, of course, is figuring out which situation you are actually in. It's very common to start a program thinking it is a short-term hack, and later on find that it's so useful that you're still developing/maintaining it years later. In that situation your life will be much less unpleasant if you didn't make any short-sighted design decisions at the beginning of the program's lifetime.

How should the C++ standard be used

I have this classic question of how should the C++ Standard (I mean the actual official document of the finalized ones) e.g. C++98, C++03 be used to learn and teach C++. My idea is only from the point of view of an average C++ user and not from the point of view of the language lawyers or someone who wishes to be in the Standards committee, compiler writers and so on.
Here are my personal thoughts:
a) It is aweful place to start learning C++. Books like "C++ in a Nutshell", "The C++ programming Language" etc do a very good job on that front while closely aligning with the Standard.
b) One needs to revert to the Standard only when
a compiler gives a behavior which is not consistent with what the common books say or,
a certain behavior is inconsistent across compilers e.g. GCC, VS, Comeau etc. I understand the fact that these compilers could be inconsistent is in very few cases / dark corners of the language e.g. templates/exception handling etc. However one really comes to know about the possible different compiler behaviors only when either one is porting and/or migrating to a different environment or when there is a compiler upgrade e.g.
if a concept is poorly explained / not explained in the books at hand e.g. if it is a really advanced concept
Any thoughts/ideas/recommendation on this?
The C++ language standard would be an absolutely terrible place to start learning the language. It is dense, obtuse, and really long. Often the information you are looking for is spread across seven different clauses or hidden in a half of a sentence in a clause completely unrelated to where you think it should be (or worse, a behavior is specified in the sentence you ignored because you didn't think it was relevant).
It does have its uses, of course. To name a few,
If you think you've found a bug in a compiler, it's often necessary to refer to the standard to make sure you aren't just misunderstanding what the specified behavior is.
If you find behavior that is inconsistent between compilers, it's handy to be able to look up which is correct (or which is more correct), though often you'll need to write workarounds regardless.
If you want to know why things are the way they are, it is often a good reference: you can see how different features of the language are related and understand how they interact. Things aren't always clear, of course, but they often are. There are a lot of condensed examples and notes demonstrating and explaining the normative text.
If you reference the C++ standard in a post on Stack Overflow, you get more a lot more upvotes. :-)
It's very interesting to learn about the language. It's one thing to write code and stumble through getting things to compile and run. It's another thing altogether to go and try to understand the language as a whole and understand why you have to do things a certain way.
The standard should be used to ensure portability of code.
When writing basic c++ code you shouldn't need to refer to the standards, but when using templates or advanced use of the STL, reference to the standard is essential to maintain compatibility with more than one compiler, and forward compatibility with future versions.
I use g++ to compile my C++ programs and there I use the option -std=c++0x (earlier, -std=c++98) to make sure that my code is always standard compliant. If I get any warning or error regarding standard compliance, I research on that to educate myself and fix my code.

Learning C when you already know C++?

I think I have an advanced knowledge of C++, and I'd like to learn C.
There are a lot of resources to help people going from C to C++, but I've not found anything useful to do the opposite of that.
Specifically:
Are there widely used general purpose libraries every C programmer should know about (like boost for C++) ?
What are the most important C idioms (like RAII for C++) ?
Should I learn C99 and use it, or stick to C89 ?
Any pitfalls/traps for a C++ developer ?
Anything else useful to know ?
There's a lot here already, so maybe this is just a minor addition but here's what I find to be the biggest differences.
Library:
I put this first, because this in my opinion this is the biggest difference in practice. The C standard library is very(!) sparse. It offers a bare minimum of services. For everything else you have to roll your own or find a library to use (and many people do). You have file I/O and some very basic string functions and math. For everything else you have to roll your own or find a library to use. I find I miss extended containers (especially maps) heavily when moving from C++ to C, but there are a lot of other ones.
Idioms:
Both languages have manual memory (resource) management, but C++ gives you some tools to hide the need. In C you will find yourself tracking resources by hand much more often, and you have to get used to that. Particular examples are arrays and strings (C++ vector and string save you a lot of work), smart pointers (you can't really do "smart pointers" as such in C. You can do reference counting, but you have to up and down the reference counts yourself, which is very error prone -- the reason smart pointers were added to C++ in the first place), and the lack of RAII generally which you will notice everywhere if you are used to the modern style of C++ programming.
You have to be explicit about construction and destruction. You can argue about the merits of flaws of this, but there's a lot more explicit code as a result.
Error handling. C++ exceptions can be tricky to get right so not everyone uses them, but if you do use them you will find you have to pay a lot of attention to how you do error notification. Needing to check for return values on all important calls (some would argue all calls) takes a lot of discipline and a lot of C code out there doesn't do it.
Strings (and arrays in general) don't carry their sizes around. You have to pass a lot of extra parameters in C to deal with this.
Without namespaces you have to manage your global namespace carefully.
There's no explicit tying of functions to types as there is with class in C++. You have to maintain a convention of prefixing everything you want associated with a type.
You will see a lot more macros. Macros are used in C in many places where C++ has language features to do the same, especially symbolic constants (C has enum but lots of older code uses #define instead), and for generics (where C++ uses templates).
Advice:
Consider finding an extended library for general use. Take a look at GLib or APR.
Even if you don't want a full library consider finding a map / dictionary / hashtable for general use. Also consider bundling up a bare bones "string" type that contains a size.
Get used to putting module or "class" prefixes on all public names. This is a little tedious but it will save you a lot of headaches.
Make heavy use of forward declaration to make types opaque. Where in C++ you might have private data in a header and rely on private is preventing access, in C you want to push implementation details into the source files as much as possible. (You actually want to do this in C++ too in my opinion, but C makes it easier, so more people do it.)
C++ reveals the implementation in the header, even though it technically hides it from access outside the class.
// C.hh
class C
{
public:
void method1();
int method2();
private:
int value1;
char * value2;
};
C pushes the 'class' definition into the source file. The header is all forward declarations.
// C.h
typedef struct C C; // forward declaration
void c_method1(C *);
int c_method2(C *);
// C.c
struct C
{
int value1;
char * value2;
};
Glib is a good starting point for modern C and gets you used to concepts like opaque types and semi-object orientation, which are common stylistically in modern C. On the other end of the spectrum standard POSIX APIs are kind of "classical" C.
The biggest gap in going from C++ to C isn't syntax, it's idiom and there, like C++, there are different schools of programming. You'll write fairly different C if you doing a device driver vs., say, an XML parser.
Q5. Anything else useful to know?
Buy a copy of K&R2 and read it through. On a cost per page basis it'll probably be the most expensive book on computing you'll ever buy with your own money but it will give you a deep appreciation for C and the thought processes that went into it. Doing the exercises will also hone your skills and get you used to what is available in the language as opposed to C++.
Taking your questions in order:
Unfortunately, there's nothing like Boost for C.
Nothing that's really on the order of RAII either.
The only compiler that tries to implement C99 is Comeau.
Lots of them all over the place, I'm afraid.
Quite a bit. C takes quite a different mindset than C.
Some of those may seem rather terse, but such is life. There are some good libraries for C, but no one place like Boost that they've been collected together or given a relatively uniform interface like Boost has done for C++.
There are lots of idioms, but many of them are in how you edit your code, such as sort of imitating RAII by writing an fopen() and a matching fclose() in quick succession, and only afterwards writing the code in between to process the data.
The pitfalls/traps that wait around every corner mostly stem from lack of dynamic data structures like string and vector, so you frequently have to write such things yourself. Without operator overloading, constructors, etc., it's considerably more difficult to make them really general purpose. Lots of libraries have them, but you end up rolling your own anyway because:the library doesn't do quite what you want, orusing the library is more work than it's worth.
The difference in mindset is almost certainly the biggest thing, at least for me. When I'm writing C++, I concentrate almost all my real effort on designing the cleanest possible interfaces, and I tend to treat the implementation of an interface as almost throwaway code. For the most part, I don't plan on making minor tweaks to that part of the code -- as long as the interface is good, replacing the entire implementation is usually easy enough that I don't worry about it much.
In C, it seems (at least to me) much more difficult to separate the interface from the implementation nearly as thoroughly or cleanly. As such, I tend to spend a lot more time trying to implement every part of the code as cleanly as possible, because later changes tend to be more difficult and throwing away and replacing pieces that aren't very good is substantially less likely to work out very well.
Edit (since people have raised questions about C99 support): While my statement about lack of C99 support may seem harsh, the fact is that it's true.
MS VC++: supports C95, and has a couple C99 features (e.g. C++ style comment delimiters), mostly because C99 standardized what they'd previously had as an extension.
Gnu: According to C99 Features Status page, the most recent iteration of gcc (4.4) has some C99 features, but some (including VLAs) are characterized as "broken", and others as "missing". Some of the missing "features" are really whole areas, not individual features.
PCC: The PCC site claims C99 conformance only as a goal for the future, not as a present reality.
Embarcadero Technologies (nee Borland) don't seem to say anything about conformance with C99 at all -- from the looks of things, the last time they worked on the C compiler may well have been before C99 was even released.
Microsoft openly states that they have no current plans for supporting C99, and they're not going to even consider it until VS 2010 is released. Though I can't find any public statements about it, Embarcadero appears about the same: no hint of a current plan, and nor even that they're going to consider working on it anytime soon.
While gcc and pcc both seem to have plans, they're currently just that: plans. They both openly admit that at the present time, they aren't really even very close to conforming with C99.
Here's a quick reference of some of the major things you'll want to know.
This is advice you didn't ask for: I think most potential employers take it as a given that if you C++ you know C. Learning the finer points of C, while an interesting academic exercise, will IMO not earn you a lot of eligibility points.
If you ever end up in a position of needing to do C, you'll catch on to the differences quickly enough.
But don't listen to me. I was too lazy and stupid to learn C++ :)
Anything else useful to know ?
C99 is not subset of c++ any revision, but separate language.
Just about the biggest shock I had when I went back to C was that variables are defined at the function level - i.e. you can't scope variables inside a block(if statement or for loop) inside a function.
Except for very few cases, any C code is valid C++, so there isn't actually anything new you should learn.
It's more a matter of unlearning.
Not using new, not using classes, defining variables at the beginning of a code block, etc.
In a strict sense, C++ is not object-oriented, but it's still procedural with support for classes. That said, you are actually using procedural programming in C++ already, the most shocking change will be not having classes, inheritance, polymorphism, etc.
As C++ is almost a superset of C89, you should know just about all of C89 already. You probably want to concentrate on the differences between C89 and C99.

Dynamic slicing in C/C++

After reading the book of debugging from Andreas Zeller, I became interested in Dynamic Slicing.
At the moment I only found relevant tools for Java analysis. Do you know such tools for C/C++?
A little information in addition to Rob's
the Wisconsin Program-Slicing Tool has evolved in a tool called CodeSurfer. Good news: it's commercially available and supported, and it works great for what it does. Bad news (perhaps): it does not actually produce a reduced program that computes the same value that you selected, but it's very convenient for navigating source code that you have not written.
Frama-C handles only C (no C++ for the foreseeable future). It is nice, not great, for navigating source code, but it can produce an equivalent smaller program for the criterion that you specify, if the original program is of the kind that it can analyze automatically (no recursion, no dynamic allocation). Frama-C is Open Source and has a mailing list in which your questions will be welcome if you are interested in the techniques it uses.
The reason CodeSurfer does not risk itself to produce an equivalent program and Frama-C can only do it for code with embedded-like restrictions is, in short, that doing so requires knowing the values of pointers, which can be arbitrarily difficult to compute with precision.
There's a tool listed on the Wikipedia page you cite. It's for C, so I guess it could work for whatever "C/C++" is.
Wisconsin Program-Slicing Tool
Also for C, and also mentioned on the Wikipedia page:
Frama-C
Giri implements dynamic backwards slicing in LLVM compiler, which as far as I know, is the latest effort to build a usable, effective and thread-aware dynamic slicer in modern compilers.