Tuesday, October 7, 2014

Digest for comp.lang.c++@googlegroups.com - 22 updates in 5 topics

comp.lang.c++@googlegroups.com Google Groups
Unsure why you received this message? You previously subscribed to digests from this group, but we haven't been sending them for a while. We fixed that, but if you don't want to get these messages, send an email to comp.lang.c+++unsubscribe@googlegroups.com.
"Öö Tiib" <ootiib@hot.ee>: Oct 06 05:42PM -0700

> > of your library.
 
> I think that using my library I can write much more readable code
> than using a vector algebra library.
 
Indeed, when you need to add two vectors. We do not use linear
algebra library for to add two vectors or few scalar values.
We use it for complex linear algebra and geometry. The more
complex it gets the more unfortunate it is that linear algebra
libraries do not care about units. So if we need to rotate or
to translate your inches then we have to part with unit-safety
in most complex parts of our calculations.
David Brown <david.brown@hesbynett.no>: Oct 07 10:22AM +0200

> code less than 64 KB. However, as I now see so much interest, I will
> try to keep those platforms into account, but without removing the
> requirement for some C++11 conformance.
 
As others have noted, TIOBE is /completely/ pointless as a judge of how
much something is used.
 
There are massive amounts of C code in common use on all sorts of
platforms, and much of it is under continuous development.
 
Regarding embedded systems, there is no magical "64KB" boundary as you
seem to think. There is, however, a stronger bias towards C rather than
C++ as systems get smaller. At the bottom end, small microcontrollers
often have very limited cpus - they are barely suitable for C
programming, never mind C++ style programming. Toolchain vendors for
such devices are limited, and their tools are limited - often there
simply are no C++ compilers available.
 
For bigger processors, C is still the preferred choice for a lot of
embedded programming - and when C++ is used, it is often used in a way
that differs significantly from desktop or "big system" C++ programming.
 
In particular, in small embedded systems there is an emphasis on code
size (thus one avoids large libraries), static behaviour (heaps, dynamic
memory, virtual functions, etc., are banned or discouraged), clear code
flow (so you avoid exceptions), and code correctness (this also means
knowing all your code, and therefore keeping source sizes to the minimum).
 
I think, however, there is a trend towards more C++ even in small
systems (just as assembly has been mostly pushed out in favour of C).
Part of this is that "small" microcontrollers have been getting "bigger"
(in particular, Cortex M cores have pushed out a lot of 8-bit cores).
Part of this is that the tools are getting better, and part of it is
that the language is getting better (C++11 has a lot of improvements).
 
Regarding compatibility of a C++ library with "small embedded C++",
there are a few things to consider:
 
There should be no use of exceptions or RTTI - these are almost always
disabled on small systems. Some embedded development tools do not have
support for them at all, and even when they are supported they lead to
very significant extra library code, limits on optimisation, extra code
in use, and most importantly, exceptions make it hard to be sure that
everything is correct because they introduce "hidden gotos".
 
There should be no reliance on the heap. With small systems
programming, you have limited memory, and you need to know that
everything fits - you do not want to leave memory management to
run-time. As much as you possibly can, you want all memory to be
allocated statically so that you can see exactly what is used, and check
it at compile-time. It also means smaller and faster code - on some
processors, several times faster. One "innocent" use of std::vector
rather than std::array can use up half your code flash space and make it
impossible to analyse your memory usage fully.
 
Virtual functions, and polymorphism in general, should be avoided unless
they really help. Multiple inheritance is right out. In general, you
want the compiler to know as much as possible at compile time. It
doesn't matter if that means re-compiling lots of code in every build -
compile time is cheap, but run time is expensive.
c.milanesi.bg@gmail.com: Oct 07 03:12AM -0700

David Brown wrote:
> > requirement for some C++11 conformance.
 
> As others have noted, TIOBE is /completely/ pointless as a judge of how
> much something is used.
 
I am eager to know which are your more reliable sources regarding the use of programming languages and programming tools.
 
> There are massive amounts of C code in common use on all sorts of
> platforms, and much of it is under continuous development.
 
I agree.
 
> Regarding embedded systems, there is no magical "64KB" boundary as you
> seem to think.
 
There is a magical boundary, that is the fact that a 16-bit pointer can address only 65536 different memory locations. Many processors have machine instructions containing 16-bit pointers, for example Zilog Z80 and Intel 8086.
 
> programming, never mind C++ style programming. Toolchain vendors for
> such devices are limited, and their tools are limited - often there
> simply are no C++ compilers available.
 
I agree.
 
> For bigger processors, C is still the preferred choice for a lot of
> embedded programming - and when C++ is used, it is often used in a way
> that differs significantly from desktop or "big system" C++ programming.
 
I agree.
 
> memory, virtual functions, etc., are banned or discouraged), clear code
> flow (so you avoid exceptions), and code correctness (this also means
> knowing all your code, and therefore keeping source sizes to the minimum).
 
I agree.
 
> (in particular, Cortex M cores have pushed out a lot of 8-bit cores).
> Part of this is that the tools are getting better, and part of it is
> that the language is getting better (C++11 has a lot of improvements).
 
I agree, but actually I don't know how much of C++11 is supported by embedded systems development tools.
 
> There should be no use of exceptions or RTTI ...
> There should be no reliance on the heap. ...
> Virtual functions, and polymorphism in general, should be avoided ...
 
I developed my library targeted for non-real-time systems with more that 1 MB of code space (I prefer to use numbers instead of generic phrases as "big memory"), but as I see that it is considered more useful for small embedded-systems, I am going to change it, re-targeted also for small-memory real-time systems.
 
--
Carlo Milanesi
Wouter van Ooijen <wouter@voti.nl>: Oct 07 12:24PM +0200

>> Part of this is that the tools are getting better, and part of it is
>> that the language is getting better (C++11 has a lot of improvements).
 
> I agree, but actually I don't know how much of C++11 is supported by embedded systems development tools.
 
GCC targets a lot of the small chips.
 
>> There should be no use of exceptions or RTTI ...
 
I agree
 
>> There should be no reliance on the heap. ...
 
I agree halfway: new/new[] is ok, but delete/delete[] is not. Hence the
only practical use of new is in the startup.
 
>> Virtual functions, and polymorphism in general, should be avoided ...
 
Here I am not so sure. run-time polymorphism can and probably should be
used when it offers an advantage (code size!). compile-time polymorphism
is OK.
 
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 07 11:27AM

>> those other than that the benefits of C++ may be less significant for
>> small programs.
 
> According the TIOBE index [...]
 
Here we go again.
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
David Brown <david.brown@hesbynett.no>: Oct 07 02:21PM +0200

>> how much something is used.
 
> I am eager to know which are your more reliable sources regarding the
> use of programming languages and programming tools.
 
Me too :-)
 
There are various surveys done that give some indication. But TIOBE
makes ratings based on the number of questions or searches on particular
topics, which has very poor correlation with the actual usage. When
there is a trendy new language, you will get lots of hits even though
few people actually use it - the people who have used C for the last ten
years will continue to do so without searching google every time they
want to use a new function, and without being noticed by TIOBE.
 
 
> can address only 65536 different memory locations. Many processors
> have machine instructions containing 16-bit pointers, for example
> Zilog Z80 and Intel 8086.
 
I have used a /lot/ of 8-bit, 16-bit and 32-bit microcontrollers. Yes,
a 16-bit pointer alone can only address 64 KB. But there are plenty of
8-bit and 16-bit microcontrollers that address more than 64 KB using
various methods, and there are plenty of 32-bit microcontrollers with
far less than 64 KB memory (flash and ram).
 
There are 8051/8052 devices that can address megabytes of memory - you
would have to be seriously masochistic to program them in "real" C++
(i.e., using heaps, exceptions, polymorphism, etc.). There are Cortex
M3 devices with 16K flash that can handle these things perfectly well.
 
That is why it is better to think in terms of "small" or "resource
limited" microcontrollers, rather than giving an artificial boundary
such as 64 KB code space. And since there are no clear quantitative
boundaries, it is better to talk about "small" and "big" systems, unless
of course you have specific size data to deal with.
 
And for such small systems, there is often a limited - but very useful
and powerful - subset of C++ that works well. I am very glad that you
are thinking of such systems in your library, but I would like you to be
aware of what that really means. For example, compact code size is
important, but not nearly as important as avoiding exceptions or dynamic
memory.
 
>> lot of improvements).
 
> I agree, but actually I don't know how much of C++11 is supported by
> embedded systems development tools.
 
gcc is far and away the most popular C++ compiler for embedded systems,
and has had solid C++11 support for a good while. Of course, in the
embedded world it is common to have to use older tools, or more limited
tools, especially for older devices. But you are writing a new library,
for use in new code and new systems - if C++11 makes your code better or
easier to use (such as by using "auto", explicit conversion operators,
and inferred return types), then use them. Most of your target audience
in the embedded world will be using Cortex M devices with a fairly
recent gcc (or llvm/clang, as ARM now prefers) and will have good C++11
support. Some potential users will miss out - but you can't please
everyone, and C++11 gives many advantages.
 
David Brown <david.brown@hesbynett.no>: Oct 07 02:34PM +0200

On 07/10/14 12:24, Wouter van Ooijen wrote:
> c.milanesi.bg@gmail.com schreef op 07-Oct-14 12:12 PM:
>> David Brown wrote:
>>> On 06/10/14 19:38, c.milanesi.bg@gmail.com wrote:
<snip>
 
>>> There should be no reliance on the heap. ...
 
> I agree halfway: new/new[] is ok, but delete/delete[] is not. Hence the
> only practical use of new is in the startup.
 
I halfway agree with your halfway agreement...
 
Without delete/delete[]/free, you don't get memory fragmentation or
non-deterministic calls, and once you've finished your startup you
either have enough memory, or you don't. Your malloc (underlying the
new/new[]) just treats memory as a simple stack.
 
However, static allocation is still more amenable to compile-time
checking, and still leads to smaller and faster code (especially on
chips that have poor address registers).
 
 
> Here I am not so sure. run-time polymorphism can and probably should be
> used when it offers an advantage (code size!). compile-time polymorphism
> is OK.
 
Yes, compile-time polymorphism is fine. Run-time polymorphism and
virtual functions /can/ be a good thing, and often compare well to
alternatives such as tables of function pointers or large switch
statements. But they should only be used when they really are useful.
 
In particular, you want to avoid unnecessary layers of abstractions in
embedded systems. It can be tempting to make things like a "GPIO"
class, and then have subclasses like "ActiveLowGPIO" and end up with a
really nice, flexible and extendible hierarchy to isolate application
code from the details of controlling pins on the microcontroller. But
then you find that activating your pin leads to virtual function
lookups, and large amounts of code and runtime when you actually just
wanted a single assembly instruction. Compile-time polymorphism and
careful use of templates with inline functions can give you better results.
Wouter van Ooijen <wouter@voti.nl>: Oct 07 03:04PM +0200

David Brown schreef op 07-Oct-14 2:34 PM:
 
> However, static allocation is still more amenable to compile-time
> checking, and still leads to smaller and faster code (especially on
> chips that have poor address registers).
 
I fully agree that static (or stack) allocation is by far to be
preferred, if only because potential problems show up at link time.
 
> lookups, and large amounts of code and runtime when you actually just
> wanted a single assembly instruction. Compile-time polymorphism and
> careful use of templates with inline functions can give you better results.
 
been there, done that :)
 
http://www.embedded.com/design/programming-languages-and-tools/4428377/Objects--No--thanks---Using-C--effectively-on-small-systems-
 
(I'll give a talk about this at meeting C++ in Berlin)
 
Wouter
scott@slp53.sl.home (Scott Lurndal): Oct 07 01:43PM

>> much something is used.
 
>I am eager to know which are your more reliable sources regarding the use o=
>f programming languages and programming tools.
 
Noting that TIOBE is useless doesn't imply that there is some other
source with better data. It is unlikely that any source has valid
data regarding the worldwide use of compiled languages.
 
 
>There is a magical boundary, that is the fact that a 16-bit pointer can add=
>ress only 65536 different memory locations. Many processors have machine in=
>structions containing 16-bit pointers, for example Zilog Z80 and Intel 8086=
 
Both of which have been obsolete for over two decades. ARM A-profile
processors now support 64-bit code, and I would expect that much like
Atom, 64-bit support will migrate into some ARM M-profile parts in
the future.
 
>> that the language is getting better (C++11 has a lot of improvements).
 
>I agree, but actually I don't know how much of C++11 is supported by embedd=
>ed systems development tools.
 
Very little. Many projects are limited by validation cycles on the
toolsets, and compatability with proprietary binary libraries. In many
cases, this limits them to using C++98 features or earlier.
 
scott
David Brown <david.brown@hesbynett.no>: Oct 07 03:51PM +0200

On 07/10/14 15:04, Wouter van Ooijen wrote:
 
> been there, done that :)
 
> http://www.embedded.com/design/programming-languages-and-tools/4428377/Objects--No--thanks---Using-C--effectively-on-small-systems-
 
There is a lot in that article that is /exactly/ what I meant, and it
will save me some time with the details. Thanks!
scott@slp53.sl.home (Scott Lurndal): Oct 07 01:58PM

>non-deterministic calls, and once you've finished your startup you
>either have enough memory, or you don't. Your malloc (underlying the
>new/new[]) just treats memory as a simple stack.
 
I've worked on two large-scale (hundreds of processors) operating systems
written in C++, and written two hypervisors in C++.
 
While we did not implement a heap allocator per-se, and the global
new and delete operators had function definitions that invoked a
kernel panic, we did overload the new and delete operators for classes
implementing objects with dynamic lifetimes using a pool-based allocator
to allocate from. The pool-based allocator invoked the OS page-allocator
for backing store.
 
David's remaining points (no RTTI, no exceptions, limited multiple inheritence[*])
remain.
 
[*] It was ok to inherit from multiple abstract (pure virtual) classes, but only
one concrete or partially virtual class.
 
 
>virtual functions /can/ be a good thing, and often compare well to
>alternatives such as tables of function pointers or large switch
>statements. But they should only be used when they really are useful.
 
Implementing interfaces (in the java sense) is the prime use for
virtual functions in real-time code.
 
For example:
 
/**
* Pure virtual interface class for dispatchable work items.
*
* A class that needs to schedule a work task for the next available
* dispatching opportunity (which come in two flavors: next core idle
* or next guest intercept) will implement this interface and provide
* a ::do_work function to handle the work item.
*/
class c_worker {
public:
 
/**
* Function called when the dispatcher schedules a work item.
*
* @param arg1 An opaque argument.
* @param arg2 An opaque argument.
* @param arg3 An opaque argument.
* @param arg4 An opaque argument.
*/
virtual void do_work(void *arg1, void *arg2, void *arg3, void *arg4) = 0;
virtual ~c_worker() {};
};
 
/**
* Idle core entry point. Wait for work and dispatch as necessary.
*/
void
c_dispatcher::idle(void)
{
while (true) {
bool istate;
s_workitem *wip = NULL;
 
istate = d_lock.lock_noint();
if (!d_idlelist.is_empty()) {
wip = (s_workitem *)d_idlelist.flink();
wip->remove();
d_state = WORKING;
} else {
if (!d_interceptlist.is_empty()) {
wip = (s_workitem *)d_interceptlist.flink();
wip->remove();
d_state = WORKING;
} else {
d_idle.init();
d_state = IDLE;
}
}
d_lock.unlock_noint(istate);
if (wip != NULL) {
void *arg1 = wip->wi_arg1;
void *arg2 = wip->wi_arg2;
void *arg3 = wip->wi_arg3;
void *arg4 = wip->wi_arg4;
c_worker *wp = wip->wi_worker;
 
d_workerpool.free(wip);
 
wp->do_work(arg1, arg2, arg3, arg4);
continue;
}
d_idle.wait();
}
}
 
/**
* This class manages IDE and ATAPI devices.
*/
class c_ide: public c_worker {
 
...
/**
* Queued bootstrap task for IDE subsystem initialization. Queued to
* the bootstrap core during node initialization. Responsible for
* identification and initialization of any IDE or ATAPI devices.
*
* @param arg1 Ignored
* @param arg2 Ignored
* @param arg3 Ignored
* @param arg4 Ignored
*/
void
c_ide::do_work(void *arg1, void *arg2, void *arg3, void *arg4)
{
i_hda.init("hda");
i_hdb.init("hdb");
i_hdc.init("hdc");
i_hdd.init("hdd");
 
debugger.register_command("ide_read",
"ide_read [hda|hdb|hdc|hdd] sector-number",
&read);
}
David Brown <david.brown@hesbynett.no>: Oct 07 05:02PM +0200

On 07/10/14 15:43, Scott Lurndal wrote:
>> ress only 65536 different memory locations. Many processors have machine in=
>> structions containing 16-bit pointers, for example Zilog Z80 and Intel 8086=
 
> Both of which have been obsolete for over two decades.
 
Direct descendants of the Z80 were used in embedded systems long after
that - I believe it is only a few years since they went out of
production. The 8051 core has been "obsolete" for over three decades,
in that there have been other cpu cores available that are better in
almost every way - and yet there are still new devices being made with
(roughly) 8051 cores in them.
 
> processors now support 64-bit code, and I would expect that much like
> Atom, 64-bit support will migrate into some ARM M-profile parts in
> the future.
 
It is highly unlikely that real 64-bit support will make it to Cortex M
devices for many years - if at all. 64-bit simply has nothing to offer
such devices. 64-bit floating point, and vector processing SIMD with
64-bit (or more) lumps will probably turn up, but you do not need more
than 32-bit direct addressing on a microcontroller.
 
 
> Very little. Many projects are limited by validation cycles on the
> toolsets, and compatability with proprietary binary libraries. In many
> cases, this limits them to using C++98 features or earlier.
 
Most projects (but certainly not all) in these categories are limited to
C - and some of these are stuck at ANSI/C90. But a large amount of
embedded development for new projects is done using more modern tools,
dominated by gcc, with support for C++11 mostly complete since about
version 4.7. clang/llvm is an alternative choice, which also has
excellent C++11 support.
 
The days of expensive, slow-update-cycle proprietary embedded toolchains
are numbered. They will be slow to die out in certain niche markets -
in particular, aeronautic and automotive industries are very keen on
them. This is not because they produce better code, have more features,
or have fewer bugs - but their price tag and validation certificates
give their users certain legal protection. But for more mainstream
embedded development, such tools are increasingly seen as old-fashioned
and limited, and it is harder and harder for the vendors to compete with
free or low-priced gcc and clang toolchains that generate better code,
support newer standards, and have more features.
 
You can see this with ARM's own toolchains. Originally, they made their
own compilers. Then as the market for expensive toolchains shrunk and
the cost of keeping up-to-date increased, they bought Keil and dropped
their own compiler. Now they have dropped Keil's compiler too, and are
basing their future toolchains on clang/llvm.
peter koch <peter.koch.larsen@gmail.com>: Oct 07 01:12PM -0700

Den tirsdag den 7. oktober 2014 15.04.40 UTC+2 skrev Wouter van Ooijen:
 
> been there, done that :)
 
> http://www.embedded.com/design/programming-languages-and-tools/4428377/Objects--No--thanks---Using-C--effectively-on-small-systems-
 
> (I'll give a talk about this at meeting C++ in Berlin)
 
With all due respect, the article in that link gives an example that is very bad C++ code. A standard solution would not use inheritance - it would use a template resulting in more generic code without any virtual function call overhead.
 
/Peter
Wouter van Ooijen <wouter@voti.nl>: Oct 07 10:50PM +0200

peter koch schreef op 07-Oct-14 10:12 PM:
 
>> http://www.embedded.com/design/programming-languages-and-tools/4428377/Objects--No--thanks---Using-C--effectively-on-small-systems-
 
>> (I'll give a talk about this at meeting C++ in Berlin)
 
> With all due respect, the article in that link gives an example that is very bad C++ code. A standard solution would not use inheritance - it would use a template resulting in more generic code without any virtual function call overhead.
 
Which example in the article do you refer to? The first C++ example is
meant to demonstrate that the 'standard' OO solution of classes and
virtual methods is indeed (in most circumstances) not a good idea on a
small chip. Are the last examples what you describe as 'the standard
solution', if not, can you explain the difference?
 
Wouter
peter koch <peter.koch.larsen@gmail.com>: Oct 07 01:57PM -0700

Den tirsdag den 7. oktober 2014 22.50.12 UTC+2 skrev Wouter van Ooijen:
> small chip. Are the last examples what you describe as 'the standard
> solution', if not, can you explain the difference?
 
> Wouter
 
Sorry - I did not realize that there was a page 2 on the link. The second solution is exactly what I meant was the correct C++ solution.
 
/Peter
"Charles J. Daniels" <chajadan@gmail.com>: Oct 06 06:49PM -0700


> Brian
 
> Ebenezer Enterprises - In G-d we trust.
 
> http://webEbenezer.net
 
I like the none_of approach -- it makes it very clear you you throw an error if none_of the given container match something.
 
To make it even more clear, you could capture the lambda to an auto variable. I like that style. Like this:
 
auto matchesLoggedInUser = [&] (cmw_account_info const& a){
return a.number==request.accountNbr;
};
if(none_of(accounts.begin(),accounts.end(), matchesLoggedInUser))
throw failure...
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 07 09:26AM

On Tue, 2014-10-07, Charles J. Daniels wrote:
> };
> if(none_of(accounts.begin(),accounts.end(), matchesLoggedInUser))
> throw failure...
 
Yeah. In fact, Stroustrup spends a lot of text (in TC++PL) trying to
make people use lambdas when appropriate, but not necessarily stuff
them into long and complicated multi-line expressions.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
woodbrian77@gmail.com: Oct 07 11:58AM -0700

On Monday, October 6, 2014 8:50:10 PM UTC-5, Charles J. Daniels wrote:
> };
 
> if(none_of(accounts.begin(),accounts.end(), matchesLoggedInUser))
> throw failure...
 
That's better, but I don't like having cmw_account_info in
there. The original doesn't need that and it looks to me
like a hindrance.
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
seeplus <gizmomaker@bigpond.com>: Oct 06 04:47PM -0700

On Tuesday, October 7, 2014 5:46:14 AM UTC+11, Richard wrote:
 
> At the end of each chapter in "The C++ Programming Language", 4th
> edition, Bjarne Stroustrup has a list of advice. I found the advice
> very helpful and decided that the advice should be online somewhere.
 
On the second page of my 2004 edition it has one of the most encompassing notices you will ever find.
 
You cannot even breathe on that stuff without infringing the copyright.
Juha Nieminen <nospam@thanks.invalid>: Oct 07 07:55AM

> [Please do not mail me a copy of your followup]
 
Why would I mail you a copy of my followup?
 
> it was too long. Instead, I made a page in my user space on the
> cppreference.com wiki:
> <http://en.cppreference.com/w/User:Legalize/Advice_from_Bjarne_Stroustrup>
 
And you got permission for this from the property owners?
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
Juha Nieminen <nospam@thanks.invalid>: Oct 07 07:52AM

> return FString<CH>(str1, str2);
 
You are not returning the "return value of the constructor", because
there's no such thing. You are instantiating an object of type FString,
constructing it, and then returning it. It's that simple.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
"AP" <unixpronospam@verizon.net>: Oct 02 12:18PM -0400

"Rick C. Hodgin" wrote in message
news:220ff353-0f27-44de-ad4d-32281ee42b2c@googlegroups.com...
 
>Think about what this means...
<snip>
 
You choose to worship a human being. You choose to spread false dogma, to
misinterpret and outright falsify the Bible, to paint the very idea of faith
as something repugnant and delusional. I'm sure your intentions are good,
but if you consider the outcome, they are nothing but evil whichever way you
look at it.
The crux of your message seems to serve one purpose : to take a natural
human impulse yearning for God and spirituality and replace it with worship
of a man - and you must resort to blackmail and bribery - all that nonsense
with your versions of hell and heaven; high pressure sales tactics -
salvation today, tomorrow is too late; forgeries abound. You build a huge
strawman out of the so called Old Testament before taking it apart - relying
on "translations" that are anything but. And on top of it all, the false
piety of nitpicking on software titles is nothing short of psychotic !!
Before too late, put in an effort and do some research into the original
sources. It's never too late. And you shouldn't do it because of some
cartoonish flames, but because it seems that at some point, your soul was
actually drawn to the Truth - the kind that takes an effort to uncover.
 
 
---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com
 
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: