When to use va_list

I created a small C library that implements graph theory algorithms and bundles them for use in Python.

I send it to a friend to check it out, and he told me that va_list is “dangerous” and should not be used in this project.

So the question is. When should va_list be used?

+6
source share
4 answers

The main problem that I see is that there is no guarantee that you really got the number of arguments you were expecting and cannot verify this. This makes errors undetectable, and undetectable errors are obviously the most dangerous. va_arg also not type safe, which means that if you pass double and expect an unsigned long long , you will get garbage instead of a beautiful integer and you will not be able to detect it at compile time (This gets a lot more messy when types don't have the same size).

Depending on the data you are dealing with, this may be more or less a problem. If you pass pointers, then it becomes fatal almost instantly to omit the argument, because instead the function will take out the garbage, and this can (if the planets are correctly aligned) become a vulnerability.

If you pass "ordinary" numerical data, it depends on the critical function. In some cases, you can easily detect an error by looking at the output of the function, and in some practical cases, it really is not so much a problem if the function does not work.

All this rotates if you are really afraid to forget the arguments.

C ++ 11 has a function of a variational template that allows you to safely handle an arbitrary number of parameters. If the step from C to C ++ doesn’t do much harm, you can study it.

+8
source

In C ++ 11, va_list should never be used, since it provides a better alternative called a variational pattern , which is typeafe, whereas va_list not.

In C, you can use va_list when you need a variable function, but be careful, because it is not typical.

And yes, your friend is right: va_list dangerous. Avoid it as much as possible.

In C and C ++ 03, the standard printf library function is implemented using va_list , so C ++ 03 programmers usually avoid using this because it is not a type.

But the typeafe printf variable can be implemented in C ++ 11 because: (taken from the wiki )

 void printf(const char *s) { while (*s) { if (*s == '%' && *(++s) != '%') throw std::runtime_error("invalid format string: missing arguments"); std::cout << *s++; } } template<typename T, typename... Args> void printf(const char *s, T value, Args... args) { while (*s) { if (*s == '%' && *(++s) != '%') { std::cout << value; ++s; printf(s, args...); return; } std::cout << *s++; } throw std::logic_error("extra arguments provided to printf"); } 
+5
source

va_list has some disadvantages associated with the uncertainty of function arguments:

  • when calling such a function, the compiler does not know what types of arguments are expected, so the standard imposes some "normal conversions" before the arguments are passed to the function. integers narrower than int , all float are promoted to double . In some borderline case, you have not received what you require in the called function.
  • In the called function, you tell the compiler what type of argument you expect and how many of them. There is no guarantee that the caller will receive this right.

If you pass the number of arguments anyway, and they have the same known type, you can just pass them with a temporary array written for C99:

 void add_vertices(graph G, vertex v, size_t n, vertex neigh[n]); 

would you call it something like this

 add_vertices(G, v, nv, (vertex []){ 3, 5, 6, 7 }); 

If this calling convention looks too ugly for you, you can wrap it with a macro

 #define ADD_VERTICES(G, V, NV, ... ) add_vertices((G), (V), (NV), (vertex [NV]){ __VA_ARG__ }) ADD_VERTICES(G, v, nv, 3, 5, 6, 7); 

here ... indicates a similar concept for macros. But the result is much safer, since the compiler can perform type checking, and this is not delayed.

+1
source

If you want to implement a function in C with variable arguments, you can use va_list. For example, printf uses va_list. I don’t know why this can be dangerous.

-1
source

Source: https://habr.com/ru/post/903401/


All Articles