Monthly Archives: October 2013

CodeChix indiegogo campaign goes live

Check us out! If you donate, you’ll get some cool stuff, and get to take part in the awesomeness.


 

CodeChix – A Community of Women Learning To Code and Grow

Advertisements

Speaking and Proposal Workshop

The fine group of women in computing that I belong to, CodeChix, will be hosting another workshop on technical speaking and conference proposals this coming Saturday. There will be four speakers (I will be taking Rupa’s place), then we will work on proposals with the speakers’ support. This is an excellent opportunity. The first workshop we held on this topic was how I got my gig at the Grace Hopper Celebration. Besides, the price is right, and there will be food.

Technical Speaking and Conf. Proposal Wkshp (Women Only), Nov 2, Stanford

The Tip of the Iceberg

In my last patch, I knew that the return type (for a status code) of my newly created function wasn’t right. I didn’t want to trigger a cascade of issues, though, so I left it. Better to maintain consistency with the variable as it was declared in the original code, I thought. Besides, I didn’t know how far I’d need to propagate the change, and I didn’t want to get into another mega refactor that I couldn’t handle.

My mentor, though, asked me to fix that issue and resend the patch. That had me collecting an unsigned value (a u16) in a signed int. Sparse wasn’t complaining, and I knew it was being assigned one of two #defined values so it would be promoted with no problem, but it was still kludgy. The right thing to do was convert the declarations and return types throughout the file. Did I trigger a cascade of issues by doing that? Yes, I did.

When I changed the declaration within the helper function, I triggered warnings from the style checking script (called checkpatch) because, throughout that function, lines were indented by three spaces instead of by eight space wide tabs. There had been a problem with that line all along, but now that I had touched it, it was in my patch. I could have changed the indentation for that line and let it go, but it was better to fix the indentation and line lengths throughout the helper function. I did that, and surprise–more checkpatch warnings. Using tabs instead of spaces triggered the “too many leading tabs” warning. Besides, some of those lines were indented so deeply that there was no room left for a variable name between the indentation and the 80 character limit. The seemingly simple change from ‘u16’ to ‘int’ had led me to another function extraction.

Now that I had seen the bottom, though, it wasn’t nearly as scary as I had imagined it to be. There was a clearly defined logical chunk I could take, the innermost of three nested loops. I was able to make two of the variables local to the new function, which meant I only needed to pass three parameters. And after I moved the extracted lines to the left and squashed some, I was left with about fifty. I had a nice, neat refactor that I could be proud of.

This is how change is made, and how opportunities are found. That little red flag, that one slightly irritating thing that’s out of place, tells us where to dig in, tear down, build, create, and win. Don’t ignore it, tolerate it, or shrink from it. Put something awesome in its place.

Spaghetti

I’ve been working on this driver file, one that is full of coding style and other issues, a goldmine for OPW application submissions. After a handful of trivial changes, such as converting C99 comments to classic C style, I figured I should show that I actually do have some coding skills. Well, with spaghetti, it’s easy to get too much on your fork.

One of the functions in the file is over 500 lines long. It’s a switch statement, with other switch statements as cases, wrapped in a while loop. My plan was to extract the outer switch cases to helper functions. The first one, a small one, went well. The second one, I actually completed it somehow. The result, though, was more spaghetti.

Since so many different paths though the code are possible, I was afraid to change or eliminate any variables. So, if I saw one being assigned a value anywhere, I passed it by reference. That ended up being basically all of them. One of the mentors joked with me that since there were “eleven parameters–are you sure you didn’t miss two more?” At least my pointers didn’t blow up.

Of course, I had already put in a lot of time over the weekend trying to extract the third outer case, which is 275 lines long. After 75, I stuffed it down in the bottom of my git stash, like a doomed sewing project, never to be seen again. I’m now doing what my mentor suggested, which is extracting the inner cases. Some of those are big sloppy messes in and of themselves. The time wasn’t wasted, though. My mentor praised me for having the guts to take it on. Plus, I am really learning my way around this file.

Pointers are just variables (and how I figured this out)

After submitting a handful of coding style fixes to the OPW kernel mentors, it was time to try some real code. The driver file I’ve been working on has a function that’s over five hundred lines long, with a tangle of nested conditionals that cause some of the lines to be indented way too far. The logical thing to do was to extract some of the switch cases into their own functions.

To do it correctly, though, I needed to send a bunch of automatic variables along with the extracted lines as parameters. This included pointers. I assumed it would be easy; but my experience is mainly with pointers to structs, and when I looked at my parameter list, I was honest with myself about how fudged it looked. Plus, I didn’t have the benefit of being lazy and letting my tools do my thinking for me. I don’t own this device, so I have to fully understand every character of what goes into my patch. Without testing it.

As I walked through the extracted lines, I realized I was assuming that since pointer variables are pointers, their referencing is already taken care of, and they can be passed around with impunity. But, since that was an assumption, was it indeed correct? And even if it was, did it give me a crystal clear understanding of my pointer variables’ states? Having defined my zone of uncertainty, I could create a test program. So I ran this:


      1 #include 
      2 
      3 void foo(int *ptr)
      4 {
      5     printf("content of ptr %p\n", ptr);
      6     printf("address of ptr %p\n", &ptr);
      7     ptr = ptr + 4;
      8     printf("content of ptr %p\n", ptr);
      9     printf("address of ptr %p\n", &ptr);
     10     putchar('\n');
     11     
     12     }
     13 
     14 int main()
     15 {
     16     int a = 2;
     17     int *pa = &a;
     18     
     19     printf("content of pa %p\n", pa);
     20     printf("address of pa %p\n", &pa);
     21     putchar('\n');
     22     
     23     foo(pa);
     24     
     25     printf("content of pa %p\n", pa);
     26     printf("address of pa %p\n", &pa);
     27     
     28     return 0;
     29     }

…and got this output:


content of pa 0xbfe65f58
address of pa 0xbfe65f5c

content of ptr 0xbfe65f58
address of ptr 0xbfe65f40
content of ptr 0xbfe65f68
address of ptr 0xbfe65f40

content of pa 0xbfe65f58
address of pa 0xbfe65f5c

Not only was the pointer value unchanged by the function, which was scary proof that I was wrong, the pointer’s address was different inside the function. What? Was the pointer being passed by value like…a plain old automatic variable?

The always helpful folks at Stack Overflow confirmed my suspicions. That’s exactly what it is, and it should be handled like one.


      1 #include 
      2 
      3 void foo(int **ptr)
      4 {
      5     printf("content of ptr %p\n", *ptr);
      6     printf("address of ptr %p\n", ptr);
      7     *ptr = *ptr + 4;
      8     printf("content of ptr %p\n", *ptr);
      9     printf("address of ptr %p\n", ptr);
     10     putchar('\n');
     11     
     12     }
     13 
     14 int main()
     15 {
     16     int a = 2;
     17     int *pa = &a;
     18     
     19     printf("content of pa %p\n", pa);
     20     printf("address of pa %p\n", &pa);
     21     putchar('\n');
     22     
     23     foo(&pa);
     24     
     25     printf("content of pa %p\n", pa);
     26     printf("address of pa %p\n", &pa);
     27     
     28     return 0;
     29     }

content of pa 0xbfef91d8
address of pa 0xbfef91dc

content of ptr 0xbfef91d8
address of ptr 0xbfef91dc
content of ptr 0xbfef91e8
address of ptr 0xbfef91dc

content of pa 0xbfef91e8
address of pa 0xbfef91dc