1

I get the following compiler error, even though there is no "do" expression in my code.

gcc -Wall -g -c main.c -lasound
In file included from /usr/include/alsa/asoundlib.h:49:0,
                 from main.c:2:
main.c: In function ‘main’:
main.c:8:5: error: expected expression before ‘do’
  if(snd_pcm_hw_params_alloca(&params) < 0) {
     ^
main.c:6:30: warning: unused variable ‘params’ [-Wunused-variable]
         snd_pcm_hw_params_t *params;
                              ^~~~~~
Makefile:15: recipe for target 'main.o' failed
make: *** [main.o] Error 1

From the following minimal reproducible example:

#include <stdio.h>
#include <alsa/asoundlib.h>

int main(int argc, char **argv)
{       
        snd_pcm_hw_params_t *params;

        if(snd_pcm_hw_params_alloca(&params) < 0) {
                return 0;
        }

        exit(0);
}

I'm aware this is not a valid ALSA program. I'm also aware that it appears snd_pcm_hw_params_alloca() doesn't even return anything worthwhile to check for errors against? That's not relevant though, this should valid C code regardless, even if it abuses the API.

Where is the "do" expression? If I go to /usr/include/alsa/asoundlib.h and poke around there, I don't see anything obvious that would indicate a problem.

If I remove the conditional if test, and get:

#include <stdio.h>
#include <alsa/asoundlib.h>

int main(int argc, char **argv)
{
        snd_pcm_hw_params_t *params;

        snd_pcm_hw_params_alloca(&params);

        exit(0);
}

This will compile with no errors.

What is this?

If I look in pcm.h, I see:

#define snd_pcm_hw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_hw_params)
int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr);
void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj);
void snd_pcm_hw_params_copy(snd_pcm_hw_params_t *dst, const snd_pcm_hw_params_t *src);

However, this doesn't tell me anything. Why does the compiler produce this error?

AlphaCentauri
  • 283
  • 5
  • 12

1 Answers1

5

I'm also aware that it appears snd_pcm_hw_params_alloca() doesn't even return anything worthwhile to check for errors against? That's not relevant though, this should valid C code regardless, even if it abuses the API.

No, if snd_pcm_hw_params_alloca() does not have a value you cannot compare it against 0. For example, the following is also invalid:

void func(void) { }
void other(void) {
    if (func() < 0) { // Error
    }
}

In reality, snd_pcm_hw_params_alloca() is a macro, and it’s a wrapper for another macro, __snd_alloca. The do is there to make it behave more like a statement. You can only call it as a statement on its own line, or anywhere else where a do loop is legal.

snd_pcm_hw_params_alloca(&params);

You cannot check for errors because alloca() does not check for errors. If alloca() fails, it will just stomp on your stack, and bad things will happen. You can’t do anything about it, except not use alloca() (this is why you might hear advice to avoid alloca).

For an explanation of why the do loop is used, see: C multi-line macro: do/while(0) vs scope block

For more information about how alloca() works, see: Why is the use of alloca() not considered good practice?

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415