I have a C++ function to which I have to pass char* arguments[]. The prototype of this function is as follows:
void somefunc(char* arguments[])
To pass the above array to this function, I am generating this array from another function which can return me this char* array output, and this looks somehwhat like this.
char** genArgs(int numOfArgs,...)
{
va_list argList;
char** toRet = new char*[numOfArgs];
va_start (arguments, numOfArgs);
for(int cnt = 0; cnt < numOfArgs ; ++cnt)
toRet[cnt] = va_arg(argList, char*);
va_end(arguments);
}
I am confused how to actually write the above function correctly, given that I will be passing the inputs to function something like : genArgs(3, a.c_str(), b.c_str(), c.c_str()) or genArgs(2, a.c_str(), b.c_str())
How can I generate the above char* array without using char** (since this would have to be deleted before returning from the function to avoid memory leak).
From your declaration of genArgs, it seems that whenever you call genArgs, you know how many arguments you want to pass. Is this correct? If so (and if you are using C++11) then you can use std::array in the calling function. So instead of this:
char** arglist = genArgs (4, "MyArg1", mYaRG2", "LastArg", 0) ;
somefunc (arglist) ;
delete[] arglist ;
you can do it this way:
#include <array>
std::array<char*, 4> arglist { "MyArg1", mYaRG2", "LastArg", 0 } ;
somefunc (&arglist[0]) ;
But there is really nothing wrong with the first solution, unless you are a C++ ascetic. (However, you do need a return toRet ; statement in genArgs!)
this would have to be deleted before returning from the function to avoid memory leak
This is not entirely correct: although it is true that you need to eventually delete[] the pointer that you allocated with new[], you do not necessarily have to do it before exiting the function where the allocation happened.
You can do this:
// This allocates args; we now own the pointer
char **argsToPass = genArgs(2, a.c_str(), b.c_str());
// Make the call as usual
somefunc(argsToPass);
// Now that args are no longer needed, we delete them:
delete [] argsToPass;
The usual way would be to use an object that manages the lifetime of the array (such as a std::vector<char*> or a std::unique_ptr<char*[]>), and then to return that (so that the eventual release of the memory would be guaranteed by the type system):
std::vector<char*> genArgs(int numOfArgs,...)
{
std::vector<char*> toRet;
toRet.reserve(numOfArgs);
va_list argList;
va_start(argList, numOfArgs);
for(int cnt = 0; cnt < numOfArgs ; ++cnt) {
toRet.push_back(va_arg(argList, char*));
}
va_end(arguments);
return toRet;
}
To use this, do the following:
somefunc(&genArgs(3, a.c_str(), b.c_str(), c.c_str()).front());
Related
I have a char[][]
char c[2][2]={
{'a','b'},
{'c','d'}
};
How can I convert it to char**?
The objective here is to use the converted char** as an input for a main function, which only accepts char** as its input. Both C/C++ solutions are acceptable.
While you could easily switch from char[] to char*, the same is not possible with char[][] and char**:
your char[2][2] is a 2 dimensional array having all the elements stored contiguously. To access one element, the compiler computes the offset knowing the size of each row.
char** points to an array that contains pointers to char. To access one element, your compiler computes the offset of the pointer in the left-most, load that poitner, then access to the element.
Workaround:
char *pc[2]={c[0],c[1]};
cout << pc[1][1]<<endl; // prints out the same as c[1][1]
// you can pass `pc` when a `char**` is needed
Remark: this compiles perfectly. However, some functions with an argument like char **av expect in reality av[i] to be a null terminated c-string. In this case, although your code would compile, the results might not be what you expect (buffer overflow).
You cannot convert a char[2][2] to char**, you can only convert it to char(*)[2],
char (*p)[2] = c;
The above is a pointer to array-of-2-char. Note that you need this 2 and cannot just write char** p, since in the latter case you are not able to perform pointer arithmetic (the pointer won't know how many elements to "jump" when incrementing, and you won't be able to address the elements of your array (in this case the rows)).
You could pass the array into the function like this:
char c[2][2] = {
{'a','b'},
{'c','d'}
};
char* x[] { c[0], c[1] };
func(x); // Assuming something like: void func(char** p);
NOTE: Although this answer may explain/illustrate the problem quite well other answers are preferable that recommend creating an automatic variable char*[2]; rather than allocating with new as this answer does.
Original answer:
The problem is char c[2][2] is a contiguous block of char. The compiler allocates only 4 char objects.
When you build an array of arrays (char** c) you need to manually allocate an array of pointers to char and then allocate (or assign) and array of char to each of those pointers.
So to convert your array char c[2][2] to an array of arrays you have to first create the array of pointers and then assign the array of the first element of each array of char to that.
Something like this:
void func(char** c)
{
for(int x = 0; x < 2; ++x)
for(int y = 0; y < 2; ++y)
std::cout << c[x][y] << ' ';
std::cout << '\n';
}
int main(int, char* argv[])
{
// one contiguous block of 4 chars
char c[2][2]={
{'a','b'},
{'c','d'}
};
char** param = new char*[2]; // create your own pointer array
param[0] = &c[0][0]; // assign the first element of each char array
param[1] = &c[1][0];
func(param); // call your func
delete[] param; // cleanup
}
If you have C++11 you can use a smart pointer to prevent memory leaks if an exception is thrown or someone forgets to delete.
int main(int, char* argv[])
{
// one contiguous block of 4 chars
char c[2][2]={
{'a','b'},
{'c','d'}
};
// use a smart pointer
std::unique_ptr<char*[]> param(new char*[2]);
param[0] = &c[0][0];
param[1] = &c[1][0];
func(param.get()); // now if this throws, no memory leak
// delete[] param; // NO NEED TO DELETE
}
I want to use pointer to store a char array generated by a function, then pass it to another function as a parameter, the code looks like this:
char* randString(){
//generate a rand string formed by 6 letters and numbers
char rSet[36];//a char set contains 0-9 and A-Z
for (int i=0;i<10;i++) rSet[i]=i+48;// get ASCII of 0-9
for (int i=10;i<36;i++) rSet[i]=i+55;// get ASCII of A-Z
char rString[7];
for (int i=0;i<6;i++){
int ind=rand()%36;
rString[i]=rSet[ind];// generate the random string
}
rString[6]='\0';
return rString;
}
void Print(char *b){
cout<<b;
}
int main(int argc, char* argv[])
{
char* a=randString();
Print(a);
}
the randString() function return a string composed by 6 random letter and number, then I store it with *a . when I tracked the pointer with debug, i found the content of *a is correct, with some stuff like "VG5GH2". However, when it was passed to Print() function, the content of the pointer was lost. Even the memory address is still the same, the value in there become some completely random stuff. If I do Print(randString()) also the same thing happend. Could someone help me out about this issue? I am pretty new to C++ and still not very clear with the use of pointer. Many thanks
When you create the character array it is being created in local scope and can't be used outside that function in which you're creating it. To tackle this problem the best way you can do in the same code is by creating the character array on heap. This will give you the exact result that you want to get.
char *rString;
rString = new char[6];
Finally, one should delete the variables created on heap! and you can do it by deleting the char pointer in which you're receiving the string from function
char* randString();
As
delete []a;
at the end of your program.
Memory issue buddy you just send back first char of your random string, the others destroyed when function done its job.But if you create them with 'new' keyword you has no problem to do anything you want.I hope this will help.
char* randString(){
//generate a rand string formed by 6 letters and numbers
char rSet[36];//a char set contains 0-9 and A-Z
for (int i=0;i<10;i++) rSet[i]=i+48;// get ASCII of 0-9
for (int i=10;i<36;i++) rSet[i]=i+55;// get ASCII of A-Z
srand(time(nullptr));
char *rString=new char[7];
for (int i=0;i<6;i++){
int ind=rand()%36;
rString[i]=rSet[ind];// generate the random string
}
rString[6]='\0';
return rString;
}
void Print(char *b){
cout<<b;
}
int main()
{
char *a=randString();
Print(a);
delete[] a;
return 0;
}
You are returning a pointer to a local variable inside the function. You are referencing stack memory- which will get used by other functions, variables as soon as the method/function exits.
One of the answers here mentions "dangling pointers". That term is applicable only when you malloc() then free() and re-used the pointer;
int *i = (int *) malloc(sizeof(int));
*i = 12;
free(i); // oops
printf("i = %d\n", *i);
If you want to write functions that return strings (char*), you have two options:
Allocate the memory inside the functions and then return it
As one of the parameters, you need to get the output buffer, and output buffer size.
As you are coding in C++ - use std::string everywhere, and don't use char* at all (note to self - still on output there is a memory copy... maybe passing the std::string out parameter as reference will help...?)
Example 1, note how we call the function and then release memory. Memory management is done by the function. This is not optimal, and I do not recommend this.
// in this function, the caller must release the memory
char* randStr1(int len) {
char* c = (char*) malloc(len), *cc = c;
for (int i=0; i<len; i++) {
*cc = rand()l
*cc++;
}
return c;
}
void foo1() {
char *c = randStr1(10);
printf("%s", c);
free(c);
}
Example 2: in this example, the memory allocation is done by the caller
char* randStr2(char *buffer, uint len) {
char *c = buffer;
while (len!=0) {
*c = rand();
c++;
len --;
}
return buffer;
}
void bar1() {
char buffer[100], *p;
p = randStr2(buffer, 100);
printf("%s", buffer); // or printf("%s", p);
}
Note how in the last example we do not need to de-allocate memory from the heap. The compiler will allocate and de-allocate memory from the stack.
I'm trying to set up some generic functions in C++ to allocate memory dynamically, and this is what I got to so far:
char* init_char(uint64_t A, const char* init){
char* ptr = new char[A];
memset(ptr, '\0', A*sizeof(char));
if(init != NULL)
strcpy(ptr, init);
return ptr;
}
char** init_char(uint64_t A, uint64_t B, const char* init){
char** ptr = new char*[A];
for(uint64_t a = 0; a < A; a++)
ptr[a] = init_char(B, init);
return ptr;
}
The idea is that you just pass the dimensions (A, B) and the initialization string (init) and it return an array with all the memory allocated. However, while the first one seems to work properly, the second one returns a NULL pointer.
I've looked around but no good. Actually in some other post (Function for Dynamic Memory allocation) they seem to do something quite similar. Am I missing something here?
thanks,
your error is not to use c++.
your problem can be reduced to:
std::string initStr("initialitation string");
int a = 10;
std::vector<std::string> myStringArray(a, initStr);
Visual studio c++ shows that "string" on line 24 has one array element, but the top contains all the text that was input by the user. But when I send to PutString(), it disappears. Why?
#include <stdio.h>
void PutString( const char* pChar ){
for( ; *pChar != 0; pChar++ )
{
putchar( *pChar );
}
}
char* GetString(){
char c[100];
int i = 0;
do
{
c[i] = getchar();
}while( c[i++] != '\n' );
c[i] = '\0';
// PutString( c );
return c;
}
void main(){
char* string = GetString();
PutString( string );
}
Because c is a local variable within GetString and you are returning its address, after which it disappears (moves out of scope). That's undefined behaviour - you're not allowed to use stuff that's gone out of scope. In fact, if you run that through gcc, it tells you that quite explicitly:
qq.cpp:9: warning: address of local variable ‘c’ returned
If you want to return non-simple things (such as arrays instead of integers or floats, which make a copy for you) from a function, you need to (for example) dynamically allocate it so that it survives function return. Something like changing:
char c[100];
into:
char *c = malloc (100); // or equivalent 'new'.
(and remembering to free/delete it eventually, of course).
Even though you may see it in the debugger when you return from GetString, it's still not guaranteed as per the standards.
In any case, there's a good chance the next stack manipulation (such as calling PutString) will wipe out the information.
Here's a C++ version that does it the new/delete way:
#include <stdio.h>
void PutString (const char* pChar ){
for (; *pChar != 0; pChar++)
putchar( *pChar );
}
char* GetString (void) {
char *c = new char[100]; // memory behind c will survive ...
int i = 0;
do {
c[i] = getchar();
} while (c[i++] != '\n');
c[i] = '\0';
return c;
} // ... past here ...
int main (void) {
char* string = GetString();
PutString (string);
delete[] string; // ... until here.
return 0;
}
I should also mention that there are probably better way to get line-based input in both C (fgets or see an earlier answer of mine) and C++ (such as the string getline and the char array getline).
You are returning pointer to a variable that is local to the function in GetString(), when the function returns, the space allocated to the variable is reclaimed.
To fix these you can either dynamically allocate space for the character array or declare it as static so that the lifetime of the variable becomes the entire program.
You GetString will not work correctly as the string (char c[100]) is put onto the stack. When the function gets to the return this will be deleted.
Either use malloc or pass into the function the array.
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>