C Traps and Pitfalls

Here’s a concise paper describing common C programming pitfalls by Andrew Koening (www.literateprogramming.com/ctraps.pdf) corresponding to be book with the same title.

As a reminder to myself, I’ll spend this page summarizing common mistakes and my history with it.

Here are the mistakes that I don’t make because of certain programming habits:

  • Operator precedence: I use enough parenthesis to not rely on operator precedence
  • Pointer dereferencing: I always do *(p++) instead of *p++ unless it’s idiomatic.
  • for() or if() statements executing only first line: I always surround the block with {} even if it’s just one line. Too often we need to inject an extra line and without {} it becomes a trap.
  • Undefined side effect order: I never do something like y[i++]=x[i]
  • char* p, q: very tempting since C++ style emphasize on pointer as a type over whether the variable is a pointer. I almost never declare multiple variables in one line.
  • Macro repeating side effects: use inline functions instead whenever possible. Use templates in C++.
  • Unexpected macro associations: guard expressions with (). Use typedef.

Did these once before, adjusted my programming habits to avoid it:

  • counting down in for() loop with unsigned running variable: I stick with signed running variables in general. If I’m forced to use unsigned, I’ll remind myself that I can only stop AFTER hitting 1, but not 0 (i.e. i=0 never got executed).

Haven’t got a chance to run into these, but I’ll program defensively:

  • Integer overflow: do a<b instead of (a-b)<0. Calculate mean by adding halfway length to the smaller number (i.e. (a+b)/2 == a + (b-a)/2 given a<b). Shows up in binary search.
  • Number of bits to shift is always unsigned (i.e. -1 is a big number!)

What I learned from the paper:

  • stdio buffer on stack (registered with setbuf()) freed before I/O flushed: use static buffer (or just make sure the buffer lives outside the function call).
  • char type might be signed (128 to 255 are -128 to -1) so it sign extends during upcast. Use unsigned char go guarantee zero extend for upcasting.
  • toupper()/tolower() might be implemented as a simple macro (no checks, incorrect /w side effects)
  • Can index into a string literal: "abcdefg"[3] gives 'd'

Mistakes that I usually make when I switch back from full-time MATLAB programming:

  • Logical negation using ~ operator instead of ! operator.

Common mistakes I rarely make because of certain understanding:

  • Forgetting to break at every case in switch block. It’s hard to forget once you’re aware of the Duff’s device.
  • sizeof(a[])/sizeof(a[0]) after passing into a function does not give array length: hard to get it wrong once you understand that array (declared on stack) has meta-info that cannot be accessed beyond the stack level it’s initialized.

 965 total views,  1 views today

Does the east coast have a ‘go fig’ culture?

Nearly a year ago I went for a company sponsored training at MIT and got to see the Boston area. My first impression was that nobody in the east coast gives a damn about ‘ease of use’ issues (apparently it’s an artistic exaggeration, but you know what I mean). The signs were often wrong (contradictory), confusing or not at conspicuous places, ranging from traffic signs (lane markings are optional, plus there are plenty of last minute turns at acute angles) to the MIT summer program registration itself (intentionally not telling you where the classroom is located before you book the hotels, and there were no signs telling you how to get to the registration if you came from the back end of the building).

Here’s a funny example:

(In case if you didn’t notice, the buttons points down. Telling the people who uses it to ‘go straight to hell’, hehe.)

I understand the people in the east coast must be very smart given that they have to dance around the mess every day. For me, I’d rather focus my effort developing algorithms or solving engineering/business problems than sorting through the mess to get the basic information I need. 🙂

 736 total views

Tablet / Cell phone holder for Nissan Maxima 2001

While transferring to my new cell phone, I found a photo of my hack to create a 7″ tablet & 5.7″ cell phone holder for my Nissan Maxima 2001. It consisted of a tablet (or cell phone stand from eBay as pictured), two large binder clips and a pocket kleenex. Turns out you can use a packet of pocket Kleenex to extend the legs of the tablet/phone holder and have it snugly fit in the dummy space in the factory stereo bezel. The two binder clips was just to avoid the unit from sliding sideways. The trick is to use stick one hand of the binder clip to the gap at the sides of the front panel.

 

 718 total views

Test instrument repair services (Specific models only)

There are a few used test instrument models that I’m familiar with the common problems. I moved onto the higher end, big ticket items so I wouldn’t bother acquiring them anymore.

Nonetheless, it hurts to see a piece of good equipment going to landfill. I’d be happy to repair the following models at a moderate rate (materials included, no fix no pay) below if anybody is interested:

  • HP 6515A power supply: $400 for a problematic unit, $300 when you send in a good one for preventative recapping (the capacitors are from 1970s! They are dying.).
  • HP/Agilent 54600 series oscilloscope: display got squeezed ($200), unit losing memory/time ($200), blown input channels due to excessive voltage ($300 for 1 channel + $100 per extra channel), unstable/cannot trigger ($500).
  • HP/Agilent (Older, non-Megazoom) Infiniium series: replacing OS hard drive ($250), cannot calibrate certain channels ($400 for 1 channel + $100 per extra channel).
  • HP/Agilent Infinium 5483X and above: refer to 54830 series post.
  • TDS 500, 600, 700 series oscilloscope: SPC fail without other symptoms ($500), Acq/Attenuator fail ($600), Proc board fail ($400), Color screen bubbled ($500), Cal initialization failed ($300), upgrading all possible software options ($200, free with any other service).

Contact me at 650-804-5024. All units must be delivered to Irvine, CA for service (and shipped back/picked up) at requester’s cost.

 803 total views

Symantec Ghost in Windows hangs for mSATA to SATA adapter board Solution: Start Ghost with -NOTRIM

I was trying to image a mSATA SSD with Ghost in Windows (I’m using version 12.0.0.8023 Corporate Edition as I bought the Altiris license) and I ran into internal consistency error 8027 right at the very beginning of the copying process.

For some reason, it doesn’t happen if I boot to the DOS version (provided by Agilent) to do the cloning.

Luckily the status bar tells me what’s going on during the process. I notice it always hangs when ghost tells me that it’s TRIMming the SSD. I looked up the help file (ghost32.exe -help) and noticed that there’s a “-NOTRIM” option. Tried it and the clone completed successfully.

Turns out Symantec is aware of it. The title of the support article is called “Cloning Solid State Disk (SSD) drives fails when using the UEFI 12.0.0.x Ghost executables“.

The summary says it since older versions (11.5.1.x) does not have TRIM, this isn’t a problem, and

“Build 12.0.0.8003 (from GSS 3.0 early build) resolved the issue with the partition restore”

I’m not sure what it means. But the solution is the same as what I did: disable TRIM when copying SSD in Windows (done by the -notrim switch).

 1,882 total views

Create user account using email address (like your Microsoft account) in Windows 7/2008

If you live in a mixed environment of Windows 7 and 8/10 computers, you might want to set the usernames to be the same so you can share the files/printers without managing Homegroup.

Nonetheless, in Windows 7/2008, if you try to create a user account using the traditional tool (Local Users and Groups) in Computer Management, you are not allowed to use email address as user name because they banned the at-mark (@):

I searched the web for quite a while, came across stuff like UPN (User Principal Name) without luck (No active directory on Windows 7, nor I want to setup a domain controller in Windows 2008 for home network). Turns out the solution is dead simple: use the “User Account” from Control panel to create the user account. No questions asked!

 909 total views

Switch between 32-bit and 64-bit user written software like CVX

CVX is a very convenient convex optimization package that allows the user to specify the optimization objective and constraints directly instead of manually manipulating them (by various transformations) into forms that are accepted by commonly available software like quadprog().

What I want to show today is not CVX, but a technique to handle the many different versions of the same program targeted at each system architecture (32/64-bit, Windows/Mac/Linux). Here’s a snapshot of what’s available with cvx:

OS 32/64 mexext Download links
Linux 32-bit mexglx cvx-glx.zip
64-bit mexa64 cvx-a64.zip
Mac 32-bit mexmaci cvx-maci.zip
64-bit mexmaci64 cvx-maci64.zip
Windows 32-bit mexw32 cvx-w32.zip
64-bit mexw64 cvx-w64.zip

You can download all packages for different architectures, but make a folder for each of them by their mexext() name. For example, 32-bit Windows’ implementation can go under /mexw32/cvx. Then you can programmatically initialize the right package for say, your startup.m file:

run( fullfile(yourLibrary, mexext(), 'cvx', 'cvx_startup.m') );

I intentionally put the /[mexext()] above /cvx, not the other way round because if you have many different software packages and want to include them in the path, you can do it in one shot without filtering for the platform names:

addpath( genpath( fullfile(yourLibrary, mexext()) ) );

You can consider using computer(‘arch’) in place of mexext(), but the names are different and you have to name your folders accordingly. For CVX, it happens to go by mexext(), so I naturally used mexext() instead.

 773 total views