Empty parameter list in C function, do you write func(void) or func()?

While reviewing code for the KIARA project I came across a change set which read like this:

- void super_duper_func () {
+ void super_duper_func (void) {

I was puzzled, what’s the difference anyway except from making it explicitly clear that there are no parameter expected? Well, I was wrong. The ISO 9899 standard (read: C99 standard) states under paragraph ‘6.7.5.3 Function declarators (including prototypes)’ that

10 — The special case of an unnamed parameter of type void as the only item in the list
specifies that the function has no parameters.
14 — An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied.

Therefore we can conclude that even though your code may compile and work correctly, your code is not standard compliant and you may even leap a compile time error detection. Have a look a this snippet which compiled flawless with clang 3.4:

#include 

void func();

int main() {
    func("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
    return 0;
}

void func() {
    printf("in func()\n");
}

Though when you turn on all warnings in clang you will get a warning but this is easily overlooked and not very obvious:

$ clang -std=c99 -Weverything -o empty_param_list empty_param_list.c
empty_param_list.c:10:6: warning: no previous prototype for function 'func' [-Wmissing-prototypes]
void func() {
     ^
empty_param_list.c:3:6: note: this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function
void func();
     ^
          void
1 warning generated.

If you go through the code you will find a function prototype and you may think that if there was no previous prototype and the function is defined later than ‘main’ the compiler will fail anyway … In this case if you forgot the function prototype the compiler would throw an error (conflicting types for ‘func’) even if you passed no arguments.

To sum it up:

  • Create function prototypes/declarations (they go before the first function definition in your source)
  • If you don’t need any parameters explicitly write void in the parameter list (helps you with finding mistakes)
  • Turn on all warnings with either ‘-Wall’ (gcc) or ‘-Weverything’ (clang) and don’t ignore those warnings!

Const in C++, a brief overview

A word of warning at the beginning: This post is about C++ and not about C! So whatever you read here may not necessarily apply to C. Nevertheless you may have a look Sugih’s page which features are in C. Besides I’m not going to explain what references and pointers are.

Introduction

While working on the KIARA project writing C++11 code I was faced with the task of passing variables to functions which will not alter these. Or pure getter methods. And after reading a post about C++ constness I was left with more questions than really understanding. A quick search revealed thorough FAQ about const usage in C++. Here I’d like to make a short round-up of it.

How to read const

First of all, read it from right-to-left. For instance int const* const p would be read as “p is a constant pointer to a constant int”.

A few examples

string const& s

Let’s say you read something like this:

void MyClass::func (std::string const& s);

So reading from right-to-left this would say “s is reference to a constant std::string”. This implies that func is not going to modify s. But keep in mind that you may have a dangling reference here, especially if you work with multi-threaded code. If this would be a pointer instead of a reference it is still possible the pointer to be NULL.

string* const s

void MyClass::func (std::string* const s);

Again, read from right-to-left: “s is a constant pointer to a string”. s may be modified (the object itself) but s may not point to a different object. As you may have already noticed it’s not that hard to read when you stick to the “read from right-to-left” rule.

string const* const s

void MyClass::func (std::string const* const s);

This would read “s is a constant pointer to a constant string” and therefore the function guarantees (respectively the compiler enforces it) that the content of s may not be changed nor may s point to a different object.

Similar consts

Obviously some signatures mean the same thing:

void MyClass::func (const std::string& s); // you may know this from C
void MyClass::func (std::string const& s);

void MyClass::func (const std::string* s);
void MyClass::func (std::string const* s); // equivalent
void MyClass::func (std::string* const s); // Pitfall: NOT equivalent

Now, it doesn’t matter which version you use but is more a decision you have to make. If previously written code opts for one variant you should for the sake of consistency use the same way.

Methods that do not change its object

When you write a pure getter method you may want to tell your compiler that the following code may not change the object itself.

std::string const& MyClass::func () const;

The last const indicates that this function may not alter its objects data.

Conclusion

C++ is not a language you master in a few hours of training, C++ is like meditating and takes daily training.

Hunting down memory leaks

I assume you are confident using a shell, installing software and generally building software from source.

While writing C code for a networking library I did some simple stability tests by setting up a simple server replying to a client query, no magic at all just hard coded strings. Obviously in such situations you will a have an eye on a process monitor like htop.

So I just ran the server and three clients in a endless loop:

while true; do binary; done

server and three clients

A quick look in htop revealed that my code leaked memory, not much per loop (around 20-30 Bytes) but still: In code which shall be once shipped in productive environment this is fatal. You can easily recognize such problems by looking at the RES column, if this value increases without clear reason you have somewhere a memory leak.

htop

For this type of problem you take valgrind. But since valgrind warns that their support on Mac OS X being broken I had to switch over to Linux. For such cases I recommend the Fedora Security Spin which comes with a huge load of tools aimed at security, auditing, research, rescue and obviously developper.

But before analyzing you need to tweak a few things: If you compile third party libraries by yourself consider passing the compiler flags -g -O0 to make sure the compiler produces debug symbols and doesn’t optimize too much making it harder to find the leaks. So make sure you invoke the configure script as follows:

make clean
./configure CFLAGS="$CFLAGS -g -O0" CXXFLAGS="$CXXFLAGS -g -O0"
make all
sudo make install

And evidently your code has also to be built with debug symbols and optimizations turned off, I’ll show you how this looks like in my Makefile:

CC = clang
BASICOPTS = -g -O0
CFLAGS = $(BASICOPTS) -pedantic -Wall -std=c11

Using -pedantic -Wall allows the compiler to warn you about every little mistake you write, always a good idea. Personally I recommend clang since it produces better error output.

Then you are ready to go hunting memory leaks! Start valgrind as following:

valgrind --tool=memcheck --leak-check=full 
    --show-possibly-lost=no your-binary

Then after one I killed my server binary with ctrl-c and got a nice output:

==3955== 
==3955== HEAP SUMMARY:
==3955==     in use at exit: 58,693 bytes in 76 blocks
==3955==   total heap usage: 162 allocs, 86 frees, 104,671 bytes all
ocated
==3955== 
==3955== 25 bytes in 1 blocks are definitely lost in loss record 13 
of 71
==3955==    at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_m
emcheck-amd64-linux.so)
==3955==    by 0x4EB2717: zframe_strdup (zframe.c:246)
==3955==    by 0x4014B9: _recv_message (kt_server.c:119)
            [snip] 
==3955== 36 bytes in 1 blocks are definitely lost in loss record 15 
of 71
==3955==    at 0x4A08121: calloc (in /usr/lib64/valgrind/vgpreload_me
mcheck-amd64-linux.so)
==3955==    by 0x4EB2117: safe_malloc (czmq_prelude.h:445)
==3955==    by 0x4EB21BB: zframe_new (zframe.c:59)
==3955==    by 0x4EB231A: zframe_recv (zframe.c:115)
==3955==    by 0x4EB780D: zmsg_recv (zmsg.c:101)
==3955==    by 0x40144E: _recv_message (kt_server.c:115)
==3955== 
==3955== LEAK SUMMARY:
==3955==    definitely lost: 61 bytes in 2 blocks
==3955==    indirectly lost: 0 bytes in 0 blocks
==3955==      possibly lost: 1,256 bytes in 12 blocks
==3955==    still reachable: 57,376 bytes in 62 blocks
==3955==         suppressed: 0 bytes in 0 blocks
==3955== Reachable blocks (those to which a pointer was found) are n
ot shown.
==3955== To see them, rerun with: --leak-check=full --show-reachable
=yes
==3955== 
==3955== For counts of detected and suppressed errors, rerun with: -v
==3955== ERROR SUMMARY: 14 errors from 14 contexts (suppressed: 2 fro
m 2)
Killed

Which shows I’m leaking memory in my code in two places. Reading the stack-trace when we go up a few stack frames while skipping the internal calls of zeromq we see two matching lines: kt_server.c:115 and kt_server.c:119. Let’s first tackle the bigger leak at kt_server.c:119:

msg->msgData = zframe_strdup(zmsg_pop(m));

That for I have to look closely what my code does and consult the API reference of czmq:

//  Remove first frame from message, if any. Returns frame, or NULL.
// Caller now owns frame and must destroy it when finished with it.
CZMQ_EXPORT zframe_t *
    zmsg_pop (zmsg_t *self);

And that’s what I forgot: “Caller now owns frame and must destroy it when finished with it.” I simply popped memory but didn’t care about freeing it. After changing the line to

msg->msgData = zmsg_popstr (m);

I was left with the first memory leak at kt_server.c:115. My code calls _recv_message() and receives a struct with a char* to the received message. Then I simply added a new response message and called _send_message():

msg = _recv_message ();

char *response = malloc(sizeof(char) * 128);
memcpy (response, "Hello World", 12);
printf ("Request: %sn", msg->msgData);
msg->msgData = response;

_send_message (msg);

The problem here is also pretty obvious: char *msgData formerly pointing to the received message is newly pointing to my freshly malloc-ed memory without freeing the old memory. So adding free (msg->msgData); solved this leak. I’ll leave figuring out where this statement goes in as an exercise to the reader.

Also an easy mistake is to forget freeing memory in _send_message() since zframe_send() requires you to destroy the passed zframe_t.

int _send_message (message_t msg)
{
    zframe_t *frame_reply = zframe_new (msg->msgData,
        strlen(msg->msgData));
    zframe_send (&frame_reply, sock, ZFRAME_REUSE);
    zframe_destroy (&frame_reply);
    free (msg);
    return 0;
}

Did you see what’s wrong here? Let’s have a look at the struct message_t which I simplified down to the relevant:

typedef struct message_t {
    char *msgData;
} message_t;

Correct: I call free (msg); which indicates that msg is a struct on the heap (allocated by malloc()) but the member char *msgData is simply a pointer on an other memory which waits to be free’d too. Let’s assume I was tired and put it after the first free:

free (msg);
free (msg->msgData);

What would happen? Well yes, your code would probably just segfault. But why? msg points after the free() to a probably otherwise used memory or is even NULL. The manpage of free(3) clearly says that ” … the behavior is undefined if the memory area referred to by ptr has already been deallocated … ” so eventually I cannot access msgData anymore. Correct would be to deallocate the memory from inside out:

free (msg->msgData);
free (msg);

A final run of valgrind shows now: My code is memory leak free!

using valgrind in my VM

Mathias Hablützel

Mathias Hablützel is a researcher at the ICCLab with focus on network and socket programming. His interests are mainly network technologies, security and linux.

Before he joined the ICCLab he attended the ZHAW with focus on system engineering and network technologies; his bachelor thesis implemented a sailing optimization software in co-operation with MeteoSchweiz.