Core S2 Software Solutions

Understanding Code

Older article from Lost in Dev; originally written by Jeremy Bridon.

Take a look at the below code. This was from an exam I took a while back.

#include ... // for malloc(), free(), etc..
 
/*
This function acquires memory and returns
the address to the caller via the parameter target.
*/
void foo(char *target)
{
	void * buf = malloc(sizeof(char) * 10);
	(*target) = buf;
}
 
int main(void)
{
	char *line;
	foo(line); /* allocate memory */
	free(line); /* deallocate memory */
}

How should we analyze this code? First, as we naturally do as programmers, is to read though the comments and glimpse through the code itself. If you do that, you soon realize that within main(), the programmer is attempting to allocate 10 bytes (or whatever the size of char is, since that is system/compiler dependent), and returns it to the calling function. After this, the programmer attempts to release the received pointer. So far so good, but the truth is far from that.

If you think more deeply and remember your pointer usage, you might see a critical conceptual error. Pointers, both a blessing and a curse, should always raise a WARNING flag in your mind. Pointers, and the closely related heap allocation functions, are subjects of common errors for most C/C++ beginners. In the above code, we create a pointer called line on line 12. We pass said pointers to function foo. At this point you should start thinking about some issues: Am I really passing this pointer, or the memory, or what? The answer is quite surprising: No – no correct data is being passed!

The reason why the pointer line is not correctly passed down is due to the fact that you are passing a copy of the pointer, not the pointer itself! Who cares what you do with a copied pointer since it never affects the original variable passed? If you are comfortable with C++, you would immediately realize that if you use the ‘&’ symbol in the parameter list of foo, you would pass it by reference, and not a copy. Though this is a great solution, it has a critical hindrance: Passing parameters by reference is not a feature of the C programming language. Many people seem to overlook this, and don’t know how to recover. Take a look at any DirectX code. I have not yet seen any function that accepts passing arguments via reference, but strictly as double pointers, or more simply: Pointers to pointers.

The solution is simple, but requires a bit of thinking. If you don’t want to pass a copy, but a reference to it, and can’t use the reference operator, what is one to do? Well, you can pass the address of the pointer object! This means you are telling the function where to change the variable in-order for it to have effect. Take a look below and read the new comments:

#include ... // for malloc(), free(), etc
/*
This function acquires memory and returns
the address to the caller via the parameter target.
*/
 
// We are now accepting a pointer/address to a pointer as the param
void foo(char **target)
{
	void * buf = malloc(sizeof(char) * 10);
	(*target) = buf;
}
 
int main(void)
{
	char *line;
	foo(&line); /* allocate memory, we are now passing the address of a pointer */
	free(line); /* deallocate memory */
}

The only lines that changed were 5 and 13. We now received a double pointers, or sometimes called an address of a pointer, and now pass said address to the pointer line. Call me crazy, but I love the beauty of pointer usage. To me, it seems beautifully simple, yet extremely powerful! Let me know if you have some crazy pointer usage since this is a great source of finding nasty spaghetti code, which I would love to rip-apart and analyze here.

This entry was posted in News & Updates. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

Sites map