COMPGROUPS.NET | Search | Post Question | Groups | Stream | About | Register

### A remark about stupidity

• Email
• Follow

Below is some historic source code of a function written by me which is part of
some internal library 'we' are using:

---------------
static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
{
uint8_t *p;
unsigned have, want, ofs;

have = evr_msg->e - evr_msg->p;
want = evr_msg->e - evr_msg->s;
do {
have += want;
want *= 2;
} while (have < need);

ofs = evr_msg->p - evr_msg->s;
p = realloc(evr_msg, sizeof(*evr_msg) + want);
if (!p) return -1;

evr_msg = (void *)p;
evr_msg->s = (void *)(evr_msg + 1);
evr_msg->p = evr_msg->s + ofs;
evr_msg->e = evr_msg->s + want;
return 0;
}
--------------

This has been used 'in production' since some time in August, until it
finally blew up on a customer appliance this Wednesday
(2011/11/16). The error is especially ghastly because the code will
work 'most of the time' and when it doesn't, the invoker will happily
write over whatever memory management data structures malloc uses
internally with aribtrarily damageing consequences. This is the source
code equivalent of something known in German as 'Augenblicksversagen'
(blink of an eye failure) when it leads to (usually disastrous) car
crashes on motorways: Despite knowing better and having applied this
better knowledge countless times, someone suddenly does something
completely stupid (in a hurry) because his brain just chose to have a
hiccup. When writing code, it is therefore prudent to assume that
everyone will make stupid mistakes, at least once in a while, and -
despite this isn't exactly popular in "many circles", that nothing
should ever be moved from development to production without a prior
code review conducted by the person who wrote it after some time has
passed and ideally, additionally by second person who hasn't been
involved with it so far.

Humans are going to make stupid mistakes and some strategy to detect
and mitigate these early should be employed (and the guy who is
convinced that HE would never do something likes shouldn't[*]).

[*] I've surely written my share of code with deadlocks. But this is
just an ordinary programming error, not some kind of the
horrid-monster-which-lurks-in-the-deeps, and the remedy is simple (fix
the code to use the proper locking order).

 0
Reply rweikusat (2830) 11/25/2011 6:24:36 PM

See related articles to this posting

Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
> despite this isn't exactly popular in "many circles", that nothing
> should ever be moved from development to production without a prior
> code review conducted by the person who wrote it after some time has
> passed and ideally, additionally by second person who hasn't been
> involved with it so far.
>=20

Amen.

Unfortunately, in the real world, most of the source code is never
reviewed.

--=20
Andr=C3=A9 Gillibert

 0
Reply UTF 11/25/2011 6:46:23 PM

On 11/25/2011 1:24 PM, Rainer Weikusat wrote:
>[...]
> static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
> {
>      uint8_t *p;
>      unsigned have, want, ofs;
>
>      have = evr_msg->e - evr_msg->p;
>      want = evr_msg->e - evr_msg->s;
>      do {
>          have += want;
>          want *= 2;
>      } while (have<  need);
>
>      ofs = evr_msg->p - evr_msg->s;
>      p = realloc(evr_msg, sizeof(*evr_msg) + want);
>      if (!p) return -1;
>
>      evr_msg = (void *)p;
>      evr_msg->s = (void *)(evr_msg + 1);
>      evr_msg->p = evr_msg->s + ofs;
>      evr_msg->e = evr_msg->s + want;
>      return 0;
> }
>[...]
> [*] I've surely written my share of code with deadlocks. But this is
> just an ordinary programming error, not some kind of the
> horrid-monster-which-lurks-in-the-deeps, and the remedy is simple (fix
> the code to use the proper locking order).

Perhaps I'm missing something, but this doesn't look like a
locking problem.  Rather, it looks like a design problem: If the
function returns 0, the caller knows that all its old pointers to
the struct are untrustworthy, but can't discover what new pointer
value it should replace them with.

Maybe a little more context would be helpful.

--
Eric Sosman
esosman@ieee-dot-org.invalid

 0
Reply esosman2 (3096) 11/25/2011 7:24:48 PM

Eric Sosman <esosman@ieee-dot-org.invalid> writes:
> On 11/25/2011 1:24 PM, Rainer Weikusat wrote:
>>[...]
>> static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
>> {
>>      uint8_t *p;
>>      unsigned have, want, ofs;
>>
>>      have = evr_msg->e - evr_msg->p;
>>      want = evr_msg->e - evr_msg->s;
>>      do {
>>          have += want;
>>          want *= 2;
>>      } while (have<  need);
>>
>>      ofs = evr_msg->p - evr_msg->s;
>>      p = realloc(evr_msg, sizeof(*evr_msg) + want);
>>      if (!p) return -1;
>>
>>      evr_msg = (void *)p;
>>      evr_msg->s = (void *)(evr_msg + 1);
>>      evr_msg->p = evr_msg->s + ofs;
>>      evr_msg->e = evr_msg->s + want;
>>      return 0;
>> }
>>[...]
>> [*] I've surely written my share of code with deadlocks. But this is
>> just an ordinary programming error, not some kind of the
>> horrid-monster-which-lurks-in-the-deeps, and the remedy is simple (fix
>> the code to use the proper locking order).
>
>     Perhaps I'm missing something,

Presumably, the text you deleted.


 0
Reply rweikusat (2830) 11/25/2011 7:36:02 PM

Rainer Weikusat <rweikusat@mssgmbh.com> writes:
> Eric Sosman <esosman@ieee-dot-org.invalid> writes:
>> On 11/25/2011 1:24 PM, Rainer Weikusat wrote:
>>>[...]
>>> static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
>>> {
>>>      uint8_t *p;
>>>      unsigned have, want, ofs;
>>>
>>>      have = evr_msg->e - evr_msg->p;
>>>      want = evr_msg->e - evr_msg->s;
>>>      do {
>>>          have += want;
>>>          want *= 2;
>>>      } while (have<  need);
>>>
>>>      ofs = evr_msg->p - evr_msg->s;
>>>      p = realloc(evr_msg, sizeof(*evr_msg) + want);
>>>      if (!p) return -1;
>>>
>>>      evr_msg = (void *)p;
>>>      evr_msg->s = (void *)(evr_msg + 1);
>>>      evr_msg->p = evr_msg->s + ofs;
>>>      evr_msg->e = evr_msg->s + want;
>>>      return 0;
>>> }
>>>[...]
>>> [*] I've surely written my share of code with deadlocks. But this is
>>> just an ordinary programming error, not some kind of the
>>> horrid-monster-which-lurks-in-the-deeps, and the remedy is simple (fix
>>> the code to use the proper locking order).
>>
>>     Perhaps I'm missing something,
>
> Presumably, the text you deleted.

.... which was about 'humans making stupid mistakes', such as
reallocating some memory area inside a subroutine and not returning
the realloc return value to the caller ...

 0
Reply rweikusat (2830) 11/25/2011 7:39:49 PM

On 11/26/11 07:24 AM, Rainer Weikusat wrote:
> Below is some historic source code of a function written by me which is part of
> some internal library 'we' are using:
>
> ---------------
> static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
> {
>      uint8_t *p;
>      unsigned have, want, ofs;
>
>      have = evr_msg->e - evr_msg->p;
>      want = evr_msg->e - evr_msg->s;
>      do {
>          have += want;
>          want *= 2;
>      } while (have<  need);
>
>      ofs = evr_msg->p - evr_msg->s;
>      p = realloc(evr_msg, sizeof(*evr_msg) + want);
>      if (!p) return -1;
>
>      evr_msg = (void *)p;
>      evr_msg->s = (void *)(evr_msg + 1);
>      evr_msg->p = evr_msg->s + ofs;
>      evr_msg->e = evr_msg->s + want;
>      return 0;
> }
> --------------
>
> This has been used 'in production' since some time in August, until it
> finally blew up on a customer appliance this Wednesday
> (2011/11/16). The error is especially ghastly because the code will
> work 'most of the time' and when it doesn't, the invoker will happily
> write over whatever memory management data structures malloc uses
> internally with aribtrarily damageing consequences. This is the source
> code equivalent of something known in German as 'Augenblicksversagen'
> (blink of an eye failure) when it leads to (usually disastrous) car
> crashes on motorways: Despite knowing better and having applied this
> better knowledge countless times, someone suddenly does something
> completely stupid (in a hurry) because his brain just chose to have a
> hiccup. When writing code, it is therefore prudent to assume that
> everyone will make stupid mistakes, at least once in a while, and -
> despite this isn't exactly popular in "many circles", that nothing
> should ever be moved from development to production without a prior
> code review conducted by the person who wrote it after some time has
> passed and ideally, additionally by second person who hasn't been
> involved with it so far.

This looks like a case where unit tests (written before the code) would
have saved your bacon.  I'm sure only writing production code in order
to pass tests has saved me form many similar embarrassing moments!

--
Ian Collins

 0
Reply ian-news (10155) 11/25/2011 7:47:24 PM

On 11/25/2011 2:39 PM, Rainer Weikusat wrote:
> Rainer Weikusat<rweikusat@mssgmbh.com>  writes:
>> Eric Sosman<esosman@ieee-dot-org.invalid>  writes:
>>> On 11/25/2011 1:24 PM, Rainer Weikusat wrote:
>>>> [...]
>>>> static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
>>>> {
>>>>       uint8_t *p;
>>>>       unsigned have, want, ofs;
>>>>
>>>>       have = evr_msg->e - evr_msg->p;
>>>>       want = evr_msg->e - evr_msg->s;
>>>>       do {
>>>>           have += want;
>>>>           want *= 2;
>>>>       } while (have<   need);
>>>>
>>>>       ofs = evr_msg->p - evr_msg->s;
>>>>       p = realloc(evr_msg, sizeof(*evr_msg) + want);
>>>>       if (!p) return -1;
>>>>
>>>>       evr_msg = (void *)p;
>>>>       evr_msg->s = (void *)(evr_msg + 1);
>>>>       evr_msg->p = evr_msg->s + ofs;
>>>>       evr_msg->e = evr_msg->s + want;
>>>>       return 0;
>>>> }
>>>> [...]
>>>> [*] I've surely written my share of code with deadlocks. But this is
>>>> just an ordinary programming error, not some kind of the
>>>> horrid-monster-which-lurks-in-the-deeps, and the remedy is simple (fix
>>>> the code to use the proper locking order).
>>>
>>>      Perhaps I'm missing something,
>>
>> Presumably, the text you deleted.
>
> ... which was about 'humans making stupid mistakes', such as
> reallocating some memory area inside a subroutine and not returning
> the realloc return value to the caller ...

Yes, I saw that part -- which said only that there had been a
mistake, and said nothing about its nature.  What I did not see (and
did not snip) was anything that might have explained why "the remedy
is simple (fix the code to use the proper locking order)."  Two
questions remain: What is the locking issue, and how does using "the
proper locking order" get the realloc() result back to the caller?

--
Eric Sosman
esosman@ieee-dot-org.invalid

 0
Reply esosman2 (3096) 11/25/2011 10:02:04 PM

Eric Sosman <esosman@ieee-dot-org.invalid> writes:
> On 11/25/2011 2:39 PM, Rainer Weikusat wrote:
>> Rainer Weikusat<rweikusat@mssgmbh.com>  writes:
>>> Eric Sosman<esosman@ieee-dot-org.invalid>  writes:
>>>> On 11/25/2011 1:24 PM, Rainer Weikusat wrote:
>>>>> [...]
>>>>> static int grow_evr_msg_to(struct evr_msg *evr_msg, unsigned need)
>>>>> {
>>>>>       uint8_t *p;
>>>>>       unsigned have, want, ofs;
>>>>>
>>>>>       have = evr_msg->e - evr_msg->p;
>>>>>       want = evr_msg->e - evr_msg->s;
>>>>>       do {
>>>>>           have += want;
>>>>>           want *= 2;
>>>>>       } while (have<   need);
>>>>>
>>>>>       ofs = evr_msg->p - evr_msg->s;
>>>>>       p = realloc(evr_msg, sizeof(*evr_msg) + want);
>>>>>       if (!p) return -1;
>>>>>
>>>>>       evr_msg = (void *)p;
>>>>>       evr_msg->s = (void *)(evr_msg + 1);
>>>>>       evr_msg->p = evr_msg->s + ofs;
>>>>>       evr_msg->e = evr_msg->s + want;
>>>>>       return 0;
>>>>> }
>>>>> [...]
>>>>> [*] I've surely written my share of code with deadlocks. But this is
>>>>> just an ordinary programming error, not some kind of the
>>>>> horrid-monster-which-lurks-in-the-deeps, and the remedy is simple (fix
>>>>> the code to use the proper locking order).
>>>>
>>>>      Perhaps I'm missing something,
>>>
>>> Presumably, the text you deleted.
>>
>> ... which was about 'humans making stupid mistakes', such as
>> reallocating some memory area inside a subroutine and not returning
>> the realloc return value to the caller ...
>
>     Yes, I saw that part -- which said only that there had been a
> mistake, and said nothing about its nature.  What I did not see (and
> did not snip) was anything that might have explained why "the remedy
> is simple (fix the code to use the proper locking order)."  Two
> questions remain: What is the locking issue, and how does using "the
> proper locking order" get the realloc() result back to the caller?

This was supposed to be a reference to Boltar's conjecture the me
referring to 'deadlocks' as 'simple problems' must mean that I'd
ludicrously believe to never write code which deadlocks at run time.
But I actually referred to them as simple because fixing them is
simple (provided that it is known what the locking order should have
been and determining this locking order is a required design step for
'proper' multithreaded applications complicated enough to need one)
and 'program stops as soon as the problem occurs', kindly preserving
all information required for fixing it until someone notices that, is
a lot easier to deal with than errors where the program continues to
run, but either works with corrupted data or even runs along codepaths
which manifested themselves out of thin air because some halfway
overwritten function pointer caused a control transfer somewhere into
the middle of an instruction (for CPUs where such things are
possible) or so.

And there are far worse things than that. Something I had to do in the
past was to modify the Linux 2.4 ARM head.s code to work with an Intel
IXP425 processor in little-endian mode. Apparently because "big-endian
makes so much more sense" someone at Intel(!) originally decided that
nobody could possibly want to run such a CPU in a different
configuration and consequently, the memory controller was designed to
be big-endian only. In order to allow a CPU running in little-endian
mode to work with that, there's a  hardware byte-swapper sitting
between the processor and the bus and this hardware byte-swapper swaps
bytes provided the MMU is enabled and the page table entry for the
page in question has a certain flag set. By the time this code runs,
the processor is in big-endian mode and a kernel has been loaded into
RAM by the bootloader. It then needs to setup enough of a page table
to provide access to the kernel after the MMU has been enabled,
byteswap the entire contents of the RAM except the the code performing
the procedure itself, enable the MMU and reconfigure the CPU into
little-endian mode and hope for the best because every error in the
(machine) code which does all this causes the whole bastard thing to
go into a state where 'code execution' is not only not anyhow
observable except with a 'hardware debugger' I didn't have but where
it is also impossible to generate any kind of diagnostic output, be it
as primitive as lighting an LED via GPIO pin.

 0
Reply rweikusat (2830) 11/25/2011 10:51:48 PM

7 Replies
64 Views

Similar Articles

12/12/2013 7:49:42 AM
[PageSpeed]

Similar Artilces:

Stupid, stupid, stupid...
Hi All, <hangs head in shame> I've downloaded the latest patchpro from sun, and like a stupid idiot didn't read the instructions and installed the packages using pkgadd -d /export/home/luser/pproSunOSx865.9re2.2 this listed 11 packages, and I blindly installed them all. Now when I installed patchpro using the setup script it install but doesn't run properly. Is there a way roll back these packages that I have installed, and if I take a note of them, will it put the system back the way it was before, or has this overwritten some previous versions files. I have uninstalle...

Why am I so stupid?
Every little thing I try to do using STL turns into a five mile crawl through raw sewage. I want to use the STL to lex/parse some text. This must have been done at least 5.0e+75 times before, but I can't find the solution in the FAQ or in any examples. This is my utterly failed attempt: std::string s = "5.0 This is a string"; std::istringstream i(s); std::cout << "Before: \"" << s << "\"" << std::endl; float x; i >> x; std::cout << "Extracted a float: " << x << std:...

Remark?
[Sorry, this is a bit off-topic, but it was sort of inspired by \begin{rem} in latex...] In publications in my field (theoretical computer science), we use Lemma, Proposition, Theorem, Definition, Remark, ... What really is a "remark"? It sounds like marking something out again. But instead we use the word "recall" for marking something again, and "remark" for marking it the first time. The OED didn't help -- it just said that the etymological origin of "re-" in words like remark is ancient and unclear. If anyone can report regarding "remark&...

EDK 8.2 STUPID STUPID BUG (minor)
this is really minor bug, but still I wasted some good 6 hours to understand that its really a bug, and that nothing was wrong with my project. THE BUG: if processor addresses have MSB set (eg address>= 0x80000000) then those peripherals do not show in the generated address map in the system datasheet! simple as that. xdsgen does report in log files proper base addresses but in the html report the peripherals above 0x80000000 are simply missing from address map table. I generated different systems, and edited the MHS and MSS files to find out whats wrong, until I found that the error is...

Some stupid question
Hi, I'm seeing strange thing there, and I'm wondering if it is a compiler error or a misunderstanding of the standard. Here is an example of the issue : class Object { //... Some member ... public: static Object CreateObject() { return Object(); } Object & Add(int a) { // The adding code here (sorry no needed here) printf("%d\n", a); } Object() { printf("Constructor\n"); } virtual ~Object() { printf("Destructor\n"); } }; Then in the main: { //... CreateObject().Add(3).Add(4); printf("O...

A stupid question...
OK. to preface this absurd question, I feel that I should say that the company I work for will not send any of us in engineering to a course on solidworks. This creates an interesting situation, wherin I have to ask stupid questions. That being said, It IS possible to extrude a hole through all parts of an assembly(this I have done), and yet the cut does not translate to the individual part when open on its own. It seems to me, that the answer is very simple, and I just cant seem to find it on my own. Likewise, it seems to me, that a cut should be able to be made in an unfolded or flat state...

What a stupid gcc!
Look at this code: 1. #include<stdio.h> 2. 3. main() 4. { const int *pc; 5. int i = 10; 6. 7. pc = &i; 8. printf("%d\n", *pc); 9. 10. int c = 2; 11. pc = &c; 12. printf("%d\n", *pc); 13. } If I compile this code with gcc, I get: myprompt> gcc PtrTest.c PtrTest.c: In function main': PtrTest.c:9: parse error before int' PtrTest.c:10: `c' undeclared (first use in this function) PtrTest.c:10: (Each undeclared identifier is reported only once PtrTest.c:10: for each function it appears in.) myprompt> Whereas g+...

Corollary/Remark
What do I write in the preamble, and what command do I write, to get sections designed to give the pre-formed header 'Remark' and 'Corollary'? I understand I need \usepackage{amssymb}. One other thing, how do I get the Fremch circumflex, i.e. the '^' symbol, to go over an 'o'? Thanks in advance. "Jack" <nomailthanx@hotmail.com> writes: >What do I write in the preamble, and what command do I write, to get >sections designed to give the pre-formed header 'Remark' and 'Corollary'? >I understand I need \u...

Very stupid question but.....
After using perl on webservers for cgi and processing data files for past 8 years I have never had to do this tilll today and just can't seem to figure out how. "Basic"lly, how do I do input a line from the keyboard in perl? I want to do something as simple as (shown in Basic): print "What is the filename?"; input filename\$ Bill H "Bill H" <bill@ts1000.us> wrote in message news:1170876403.322501.53390@v33g2000cwv.googlegroups.com... > After using perl on webservers for cgi and processing data files for > past 8 years I have never had to do t...

stupid question
A really stupid question, I know, but is it possible/how do I lighten the entire picture at once?? Jeremy Jeremy Schoenhaar <JBSchoenhaarNOSPAM@schoenhaar.com>, you wrote on Sat, 17 Apr 2004 11:52:37 +0200: >A really stupid question, I know, but is it possible/how do I lighten the >entire picture at once?? I am not sure if it's possible to lighten all layers at once. One layer at the time you lighten by selecting the menu Layer/Colors/Brightness-Contrast... -- branko collin - dr: "have you been exposed to any user interfaces designed by engineers?" - woman: &q...

stupid windows!
I decided to look at VB 2005 Express, so I started installing it. I let it run in the background while I was replying to some e-mails. I'm typing away and suddenly a box flashes up and then disappears. Next thing I know, my computer is shutting down. It seems that the installer popped up a box that asked me if I wanted to restart. My typing must have included an enter or something at the right point and bingo, I'm shutting down. While I'm typing this article, I've twice had things pop up and suddenly I'm not typing in my newsreader anymore. (It was the firewall softwar...

When clever is stupid
Some time in the past, I wrote a line of code. It looked like this: if pu : pu = pu.url.to_s != '' ? pu : nil end There is sat, working fine, for a long time. Today, I was editing the code, doing a variation on it for a new site. I came to that line. I looked at it. I called it stupid. Sure, it's concise, but what did I gain by making it so concise over making it so that it was clearly readable a year and a half later? Not much. Sometimes clever is good, when there is a reason for it. However, that time, clever was just plain stupid. Kirk Haines On 01/09/06, k...

A stupid problem ...
I am a c++ beginner and have the following problem: I wrote a simple internet application using Dev-C++ (on Win XP) and three ininet.dll functions, something like this: #include <wininet.h> #include <stdio.h> #include <iostream> ..... HINTERNET hNet, hConn; long cZero = 0; char * NullString = 0; hNet = InternetOpenA(............); hConn = InternetOpenUrl(hNet, ......); ....... Everything works fine, I compiled the project and the exe-file runs good. But this as long as I run it on the comp on wich I programmed and compiled it. If I try to run it on another computer, I ...

How about a stupid question?
I've done a number of Solaris installs and having come from Linux, I like a GNU-ish environment. I also prefer bash and since the bash install comes very vanilla and I don't want to mess up root's environment, I've been accumulating a .bashrc that sets up the environment I prefer. To get ssh logins to work, I symlink it to ..bash_profile. Since I've never been able to really understand how shells source global profiles vs user profiles, and under which circumstances they do one and not the other, I've had to arrange it so all users symlink ~/.bashrc and ~/.bash_prof...

That stupid Witch
There are a number of things about Arcania that have many diehard Gothic fans up in arms. One of those things is the dreadful voice acting. To get an idea of how bad it is watch the following clip of "Lyrca" the Witch in the Dark Forest. This is arguably the worst voice acting in any game ever. I know the developers wanted to simply the game in order to appeal to a wider audience. I didn't realise they were targeting the under fives. http://www.youtube.com/watch?v=hzJYz7Pj--I -- Rob You'd prefer something like this (starting at 2:00)? http://www.youtube.com/watch?v=2n...

Stupid Question?
I'm trying to make it so that the left arrow key takes the item on stack Level 1 and pulls up the Equation Writer. I can do this with the "EQW" command, but I would like it to pull up a blank EQW (as it would from the keyboard) if and only if the stack is empty. Now, I can test the depth of the stack easily enough, but the EQW command doesn't seem to want to start without arguments, and I can't figure out what argument would make it come up blank. Is there any way to do this with this command, and if not, is there any way to pull up the EQW from a UserRPL program (with...

Stupid capslock!
Kill Kill KILL! <ronviers@gmail.com> wrote in message news:1161497140.084096.255430@b28g2000cwb.googlegroups.com... > Kill Kill KILL! LOL - I feel your pain. Luckily, there is a cure. http://johnhaller.com/jh/useful_stuff/disable_caps_lock/ -- Mike Russell www.curvemeister.com/forum/ On Sun, 22 Oct 2006 06:56:11 GMT, "Mike Russell" <RE-MOVEmike@Curvemeister.comRE-MOVE> wrote: ><ronviers@gmail.com> wrote in message >news:1161497140.084096.255430@b28g2000cwb.googlegroups.com... >> Kill Kill KILL! > >LOL - I feel your pain. Luckily, the...

Stupid TK
Can anyone please give me a compiled version of Tk 8.4? I have Tk 8.5 but Ruby doesn't work with that version, and I can't figure out how to compile it. I am running Windows XP. On 12/18/2009 9:00 AM, Philliam Auriemma wrote: > Can anyone please give me a compiled version of Tk 8.4? I have Tk 8.5 > but Ruby doesn't work with that version, and I can't figure out how to > compile it. I am running Windows XP. i've have some luck with downloads from: http://www.activestate.com/activetcl/ the 8.4 windows binaries are in https://www.activestate.com/act...

Stupid question for you all....
Hi Guys, I've got a question from a stupid question from a clueless computer operator's standpoint. I use Windows XP. SP2, and I've got all these neat little programs. What language do they program these neat little programs in, like Skype, Yahoo IM, AOL IM, GAIM, Weatherbug, all these neato programs... I'd like to do some programming and do an freeware program for amateur radio. but I'm freakin' clueless as to how to program... I mean, I learned to use a stinkin' computer, I should be able to learn to program, Any suggestions? Books to read? Software to get? Just...