va_arg will overflow in clang and apple mac os x? - c++

#include <cstdarg>
#include <iostream>
void print(const size_t n, ...) {
va_list args;
va_start(args, n);
for (size_t i = 0; i< n; ++i ) {
auto v = va_arg(args, uint64_t);
std::cout<< v << std::endl;
}
va_end(args);
return;
}
int main() {
print(6, 1,2,3,4,5,6);
//print(5, 1,2,3,4,5);
return 0;
};
then I got the output:
 ~/private/code/cpp/trial/ ./a.out
1
2
3
4
5
140728898420742

The problem is that your print function assumes that arguments are passed as uint64_t. When you invoke the function, you however specify the values as integer literals, so the compiler will choose to pass them as int.
If you pass the numbers as 1ULL, 2ULL etc. then things should work. Or assume that the values are of type int in function print. Note that this use of va_arg. The compiler will not warn about type mismatches and you can get pretty weird behavior. For example if by accident you pass a floating point value like 1.5.
Since you are using C++, variadic templates might be better suited to your case.

Related

Make the compiler deduce the parameter of a function before compilation

Here is an example of my problem.
#include <stdio.h>
//template<std::size_t A> <-- Tried to solve the problem by using template
void func1(const int power){
const int length = 1 << power;
int twoDArrayA[length][length];
for (int j = 0; j < power; j++)
{
/* Code */
}
}
int main() {
func1(4);
func1(3);
func1(2);
}
I wonder if I could somehow allow the compiler to deduce parameter power in func1 before it compiles. So instead of compiles one function, it compiles 4 functions in the format of func1 with different power value.
The reason for this is because I would like to use Vitis HLS to unroll the loop and partition the matrix so that it could be implemented onto a FPGA, where a variable-length loop or array cannot work properly.
You can do this with a template, but you've got the wrong syntax. It should be:
template<std::size_t power>
void func1(){
const std::size_t length = 1 << power;
int twoDArrayA[length][length];
...
}
int main() {
func1<4>();
...
}
Note that your variable length array (VLA) is legal C++ if length is a compile-time constant (as it is here). Nevertheless, std::array would be a better bet.
PS: Thanks for telling us why you want to do this. That was a nice touch.

va_list passed to a function using va_arg is not working

I've this code that plays with variadic functions:
#include <cstdarg>
#include <iostream>
template <typename T>
void bar(va_list vl) {
std::cout << va_arg(vl, T) << std::endl;
}
void foo(int n, ...) {
va_list vl;
va_start(vl, n);
while (n--) {
bar<int>(vl);
}
va_end(vl);
}
int main() {
foo(3, 1, 2, 3);
return 0;
}
Unfortunately, the output of this code is platform dependent. In GCC 7 I get:
1
2
3
while in MSVC 2015 is
1
1
1
I'm tring to write code to get the GCC output, but I suppose I'm doing something wrong and I've no idea where. Which is the correct output, if any?
Both compilers are set at maximum warning level, but they are not printing any warning.
In MSVC, being va_list an alias to char*, the output makes sense. In GCC it is a builtin type and I've no idea what happens there.
Edit:
If I change the definition of bar to void bar(va_list& vl) then the outputs are the same. Is it legal to pass a va_list by reference?
Your program invokes undefined behavior.
The semantics of C standard library in C++ is the same as in C and the content of cstdarg should be the same as stdarg.h in C. C++ standard is big, so I'll use C standard here, which is easier for me to read. From C99 7.15.3, annotation mine:
.... The object ap [of type va_list, my annotation] may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.
If you pass va_list object to another function and in that function you call va_arg, you have to call va_end in the same function.
According to the footnote 221 from C99 you can pass a pointer to va_list.
You should use modern C++11 approach. Using old fashion C variadic function is to dangerous.
You could use C++ template parameter pack, but in your case simple std::initializer_list just do the job and it is quite handy:
void foo(std::initializer_list<int> items) {
for (auto item : items) {
std::cout << item << std::endl;
}
}
int main() {
foo({1, 2, 3});
return 0;
}
demo

C++ Function with unlimited optional parameters and different choices of input variables

Been thinking about these questions for a while now but couldn't come up with an idea on how to do it.
Lets say I have a function like:
double sum( int param1 , double param2 , [ optional... ] )
{
return param1 + param2;
}
Now I want
Q1: optional parameters
Q2: unlimited amount of optional parameters without having to declare them all ofc.
Q3: use of int and double values in those optional parameters
Thanks in advance :)
If you are familiar with c++11, there is a new concept introduced called variadic templates; which in essence allows one to create functions like you have mentioned which can take a varied amount of arguements.
The syntax for declaring such function looks like:
template <typename ... Types>
void someFunc(Types ...args) {}
Another option is to use an std::initializer_list along with std::accumulate to achieve this since you already know the types of the variables you will be using. An example using your program is this:
#include <iostream>
#include <initializer_list>
#include <numeric>
using namespace std;
double sum( initializer_list<double> vals ) {
return accumulate(vals.begin(), vals.end(), 0.0);
}
int main() {
// your code goes here
cout << sum({2, 3, 4.6, 5, 6, 74.322, 1}) << endl;
return 0;
}
You want to use Variadic function.
One example shown there is quite easy to understand, which will compute the average of an arbitrary number of arguments. Note that the function does not know the number of arguments or their types.
#include <stdarg.h>
double average(int count, ...)
{
va_list ap;
int j;
double tot = 0;
va_start(ap, count); /* Requires the last fixed parameter (to get the address) */
for(j = 0; j < count; j++)
tot += va_arg(ap, double); /* Increments ap to the next argument. */
va_end(ap);
return tot / count;
}

varargs(va_list va_start) doesn't work with pass-by-reference parameter [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Are there gotchas using varargs with reference parameters
Hi, I have a problem with varargs.
Look at my code(Microsoft Visual Studio 2005 or 2008).
#include <stdarg.h>
struct Test { int a; };
void T1(int n, ...) {
va_list args;
va_start(args, n);
char* p = va_arg(args, char*);
va_end(args);
}
void T2(Test n, ...) {
va_list args;
va_start(args, n);
char* p = va_arg(args, char*);
va_end(args);
}
void T3(const Test& n, ...) {
va_list args;
va_start(args, n);
char* p = va_arg(args, char*); // p corrupt!!
va_end(args);
}
int _tmain(int argc, _TCHAR* argv[]) {
const Test t;
T1(1, "Test1");
T2(t, "Test2");
T3(t, "Test3");
return 0;
}
function T1, T2 work well. But T3 function have a problem. The pointer p doesn't point "Test3". Can't I use va_start with pass-by-reference?
Thanks in advance.
You cannot use references with va_start according to C++ Standard 18.7/3:
The restrictions that ISO C places on the second parameter to the va_start() macro in header
are different in this International Standard. The parameter parmN is the identifier of the
rightmost parameter in the variable parameter list of the function definition (the one just before the ...).
If the parameter parmN is declared with a function, array, or reference type, or with a type that is not compatible
with the type that results when passing an argument for which there is no parameter, the behavior is
undefined.
Short answer: no, you cannot do that.
NOTE: I saw the first answer which quotes the standard but I believe it is worth showing also my tests.
va_start is defined like this:
Visual 6: #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
Visual 8: #define _crt_va_start(ap,v) ( __va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), \
__alignof(v), _ADDRESSOF(v)) )
With this code:
#include <cstdio>
int main()
{
char c;
char &rc = c;
int i;
int &ri = i;
printf("char ref:%d\n", sizeof(rc));
printf("int ref:%d\n", sizeof(ri));
return 0;
}
output
char ref:1
int ref:4
Since at implementation level references are passed on stack in a similar way to pointers this represents a problem since the size differs (it is because of the macro which computes the size of the type not taking into account that the parameter is actually a reference, which is not constant but depends on actual size of the type).

Create va_list dynamically

I have a function
void foo(int cnt, va_list ap);
I need to use it, but requirement is quite strict, number of va_list vary and it will change during run-time. What I would like to do is:
create a va_list (which expects char*) form
QList<Contact*>
where Contact is a defined class
class Contact
{
public:
QString getName();
private:
QString m_name;
};
and I would like to populate in the loop va_list for example:
for (int idx = 0; idx<contacts.count(); idx++)
{
contacts.at(idx)->getName(); // this i would like to pass to va_list
}
Does anybody have a clue about how I could do this?
What you're wanting to do is to simulate the call stack so you can pass a constructed va_list to foo(). This is rather specific to the compiler ( and warning, there are differences between even 32- and 64-bit compilers ). The following code is for ENTERTAINMENT PURPOSES ONLY!!! as (if it even works on your system) it is prone to breakage. With it, I use a flat memory buffer and the populate it with a count and a bunch of character strings. You could fill it as appropriate with pointers to your strings and hand them down.
It does seem to work on my system, Windows 7 w/ Visual Studio 2008, for 32-bit applications only.
* BAD IDEA CODE FOLLOWS!!! *
#define PSEUDOSTACKSIZE ( sizeof(int) + 999 * sizeof(const char*) )
#pragma pack( push,1 )
union PSEUDOSTACK
{
int count;
char data[PSEUDOSTACKSIZE];
};
#pragma pack( pop )
void foo( int count, va_list args )
{
for ( int i = 0; i < count; i++ )
{
char *s = va_arg( args, char* );
printf( "%s\n", s);
}
}
void bar( PSEUDOSTACK data, ... )
{
va_list args;
va_start(args, data.count);
foo( data.count, args);
va_end(args);
}
// And later on, the actual test case code.
PSEUDOSTACK barData;
barData.count = 999;
char *p = barData.data + sizeof(int);
for ( int i = 0; i < 999; i++, p += sizeof(char*) )
{
*reinterpret_cast<char**>(p) = "ThisIsABadIdea";
}
bar( barData );
I'll now go hang my head in shame for thinking of such an idea.
...hmmm...maybe not portable...for sure not nice...but may solve yor problem...
va_list is (at least for visual c++) just a #define for char*
→ arguments don't need to be on the stack
→ arguments are just required to be continuous in memory
→ no need to use assembler and/or copying (see my 'just for fun answer' :-)
→ no need to worry about cleanup
efficient!
tested on w2k3 sp2 32bit + vc++ 2010
#include <stdarg.h>
#include <string>
#include <vector>
#include <iostream>
#define N 6 // test argument count
void foo(int n, va_list args);
int main(int, char*[])
{
std::vector<std::wstring> strings;
std::wstring s(L"a");
int i(0);
// create unique strings...
for (; i != N; ++i)
{
strings.push_back(s);
++s.front();
}
foo(N, reinterpret_cast<va_list>(strings.data()));
return 0;
}
void foo(int n, va_list args)
{
int i(0);
for (; i != n; ++i)
std::wcout << va_arg(args, std::wstring) << std::endl;
}
Your question is tagged C++ and there are nice ways (like streams) to avoid varargs completely in C++.
This is a great example of why va_args can cause pain. If you have any chance at all to change the signature of foo, that's your best option. Taking a std::vector<std::string> instead of va_list would just solve your problem right there.
If foo is in an external library you can't change, my next suggestion would be to find a different library.
If none of those is an option it seems like there ought to be a way to recursively build up the call list using va_list, but I couldn't figure out how to make that work.
If the number of elements in the list is limited, I would go for manual dispatch depending on the number of elements.
void call_foo(int count, ...) {
va_list args;
va_start(args, count);
foo(count, args);
va_end(args);
}
switch (contacts.count()) {
case 0: return call_foo(contacts.count());
case 1: return call_foo(contacts.count(),
contacts.at(0)->getName());
case 2: return call_foo(contacts.count(),
contacts.at(0)->getName(),
contacts.at(1)->getName());
case 3: return call_foo(contacts.count(),
contacts.at(0)->getName(),
contacts.at(1)->getName(),
contacts.at(2)->getName());
default: /* ERROR HERE, ADD MORE CASES */ return call_foo(0);
}
What you are trying to use is alloca. A va_list object can not store variables, the function call stores them, and you can only access it via va_list. These variables are only valid during the call, and they get ovverwriten afterwards.
THIS WILL NOT WORK:
va_list func(int dummy, ...)
{
va_list result;
va_start(result, dummy);
return result;
}
To allocate memory on the stack, without having to write a variadic functions use alloca. It works more or less like malloc, but you don't have to call free, it automagically frees itself when you leave the scope.
int * local = (int *) alloca(3 * sizeof(int));
local[0] = 10;
local[1] = 20;
local[2] = 30;
It's fundamentally the same as writing
int local[3];
local[0] = 10;
local[1] = 20;
local[2] = 30;
But with alloca 3 does not need to be a constant. Again you can only use it inside the enclosing scope, so do not return it from the function.
if what you want from a va_list is the multiple types in one list consider writing a union like this:
union variant
{
int i;
unsigned int u;
float f;
double d;
const char * s;
void * v;
};
It depends on compiler what is the va_list type, what are the va_start and va_end macros. You cannot do this in a standard way. You would have to use compiler-specific construction.
Maybe you can alter the 'foo' function? If so, then make it inversely - convert va_list to QList and make 'foo' accept QList.
// EDIT
Then see what the va_list type is, what the va_start and va_end macros are in your specific compiler. Then build your va_list in such a way that these macros will work on it.
<just for fun>
allowing arbitrary argument count
luckily sizeof(std::wstring) is a multiple of sizeof(int)
tested on w2k3 sp2 32bit + visual c++ 2010
#include <stdarg.h>
#include <string>
#include <vector>
#include <iostream>
#define N 6 // test argument count
void foo(int n, ...);
int main(int, char*[])
{
std::vector strings;
std::wstring s(L"a");
int i(0);
// create unique strings...
for (; i != N; ++i)
{
strings.push_back(s);
++s.front();
}
int n_stack_strings(N*sizeof(std::wstring)), // space needed for strings
n_stack(sizeof(int)+n_stack_strings); // overall stack space...needed for cleanup
__asm sub esp, n_stack_strings ; reserve stack space
std::wstring* p_stack(0);
__asm mov p_stack, esp ; get stack pointer
std::wstring* p(p_stack);
std::vector<std::wstring>::iterator string(strings.begin());
// copy to stack
for (; string != strings.end(); ++string, ++p)
new (p) std::wstring(*string);
__asm push N ; argument count...arguments right to left (__cdecl)
__asm call foo
// cleanup
for (p = p_stack; p != p_stack+N; ++p)
p->~basic_string();
__asm add esp, n_stack ; caller has to cleanup the stack (__cdecl)
return 0;
}
void foo(int n, ...)
{
int i(0);
va_list marker;
va_start(marker, n);
for (; i != n; ++i)
std::wcout << va_arg(marker, std::wstring) << std::endl;
va_end(marker);
}
</just for fun>