C++ error - returning a char array - c++

Consider the following code:
char CeaserCrypt(char str[256],int key)
{
char encrypted[256],encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); i++)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
Visual Studio 2010 gives an error because the function returns an array. What should I do?
My friend told me to change the signature to void CeaserCrypt(char str[256], char encrypted[256], int key). But I don't think that is correct. How can I get rid of the compile error?

The return type should be char * but this'll only add another problem.
encrypted is "allocated" on the stack of CeaserCrypt and might not be valid when the function returns. Since encrypted would have the same length as the input, do:
int len = strlen(str);
char *encrypted = (char *) malloc(len+1);
encrypted[len] = '\0';
for (int i = 0; i < len; i++) {
// ...
}
Don't forget to deallocate the buffer later, though (with free()).
EDIT: #Yosy: don't feel obliged to just copy/paste. Use this as a pointer to improve your coding practice. Also, to satisfy criticizers: pass an already allocated pointer to your encryption routine using the above example.

It wants you to return a char* rather than a char. Regardless, you shouldn't be returning a reference or a pointer to something you've created on the stack. Things allocated on the stack have a lifetime that corresponds with their scope. After the scope ends, those stack variables are allowed to go away.
Return a std::vector instead of an array.
std::vector<char> CeaserCrypt(char str[256],int key)
{
std::vector<char> encrypted(256);
char encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); ++i)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
There's another subtle problem there though: you're casting an integer to a character value. The max size of an int is much larger than a char, so your cast may truncate the value.

Since you're using C++ you could just use an std::string instead. But otherwise, what your friend suggested is probably best.

There are a few problems here. First up:
char CeaserCrypt(char str[256],int key)
As others have pointed out, your return type is incorrect. You cannot return in a single character an entire array. You could return char* but this returns a pointer to an array which will be allocated locally on the stack, and so be invalid once the stack frame is removed (after the function, basically). In English, you'll be accessing that memory address but who knows what's going to be there...
As your friend suggested, a better signature would be:
void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key)
I've added a few things - a size_t length so you can process any length string. This way, the size of str can be defined as needed. Just make sure char* encrypted is of the same size.
Then you can do:
for(int i = 0; i < length; i++)
{
// ...
For this to work your caller is going to need to have allocated appropriately-sized buffers of the same length, whose length you must pass in in the length parameter. Look up malloc for C. If C++, use a std::string.

If you need C compatibility make encrypted string function argument.
If not, than use C++ std::string instead C style string.
And also In your code encrypted string isn't ending with '\0'

The problem with the original code is that you are trying to return a char* pointer (to which your local array decayed) from a function that is prototyped as one returning a char. A function cannot return arrays in C, nor in C++.
Your friend probably suggested that you change the function in such a way, that the caller is responsible for allocation the required buffer.
Do note, that the following prototypes are completely equal. You can't pass an array as a parameter to normal function.
int func(char array[256]);
int func(char* array);
OTOH, you should (if you can!) decide the language which you use. Better version of the original (in C++).
std::vector<unsigned char> CeaserCrypt(const std::string& str, const int key)
{
std::vector<unsigned char> encrypted(str.begin(), str.end());
for (std::vector<unsigned char>::iterator iter = vec.begin();
iter != vec.end(); ++iter) {
*iter += key;
}
return vec;
}
Do note that overflowing a signed integer causes undefined behavior.

VS2010 is "yelling" at you because you are trying to return a value that is allocated on the stack, and is no longer valid once your function call returns.
You have two choices: 1) Allocate memory on the heap inside your function, or 2) use memory provided to you by the caller. Number 2 is what your friend in suggesting and is a very good way to do things.
For 1, you need to call malloc() or new depending on whether you are working in C or C++. In C, I'd have the following:
char* encrypted = malloc(256 * sizeof(char));
For C++, if you don't want to use a string, try
char* encrypted = new char[256];
Edit: facepalm Sorry about the C noise, I should have looked at the question more closely and realized you are working in C++.

You can just do your Ceaser cipher in place, no need to pass arrays in and out.
char * CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
return str;
}
As a further simplification, skip the return value.
void CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
}

well what you're returning isn't a char, but a char array. Try changing the return type to char*(char* and a char array are ostensibly the same thing for the compiler)
char* CeaserCrypt(char str[256],int key)
EDIT: as said in other posts, the encrypted array will probably not be valid after the function call. you could always do a new[] declaration for encrypted, remembering to delete[] it later on.

Related

How to convert a vector<wstring> to a wchar_t**?

I need to create a C compatible (friendly) return type so that my C++ functions can be used to work with C-based functions.
How I can convert a vector of wstring to a wchar_t** array?
You can iterate through the wstring vector and add each wstring::c_str() to your wchart_t** array.
Far better to avoid doing this at all if you possibly can.
If you really have no choice, you'd basically do something like allocating an array of pointers, then allocating space for each string, and copying each individual string in the input to the buffer you allocated.
wchar_t *dupe_string(std::wstring const &input) {
wchar_t *ret = new wchar_t[input.size()+1];
wcscpy(ret, input.c_str());
return ret;
}
wchar_t **ruin(std::vector<std::wstring> const &input) {
wchar_t **trash = new wchar_t*[input.size()];
for (int i=0; i<input.size(); i++)
trash[i] = dupe_string(input[i]);
return trash;
}
Based on the comments, however, I have some misgivings about this applying to the current situation though -- this assumes the input is wide strings, which would typically mean UTF-16 or UTF-32/UCS-4. If the input is really in the form of UTF-8, then the storage elements you're dealing with will really be char, not wchar_t, so your input should be narrow strings (std::string) and the matching output char ** rather than wchar_t **.
wstring is a templated instantiation of basic_string, so its c_str() function returns wchar_t*.
So, you can do something like
std::vector<const wchar_t*> pointers;
pointers.reserve(wstrVec.size());
for (auto it = wstrVec.begin(); it != wstrVec.end(); ++it) {
pointers.push_back(it->c_str());
}
const whcar_t** cptr = pointers.data();
Without more context it's difficult to advise the best way to deal with scope/lifetime issues. Are you writing a library (which suggests you have no control over scope) or providing an api for callbacks from C code you are supervising?
A common approach is to provide a sizing api so that the caller can provide a destination buffer of appropriate size:
size_t howManyWstrings()
{
return wstrVec.size();
}
bool getWstrings(const wchar_t** into, size_t intoSize /*in pointers*/)
{
const size_t vecSize = wstrVec.size();
if (intoSize < vecSize || into == nullptr)
return false;
for (size_t i = 0; i < vecSize; ++i) {
into[i] = wstrVec[i].c_str();
}
return true;
}
It sounds like your C function is expecting a pointer to a wchar_t buffer, and to be able to move this pointer around.
Well, this is mostly easy, though you'll have to manage the lifetime of the pointer. To that end, I suggest not doing this as a return type (and thus letting C ruin your API, not to mention your code's sanity), but performing this logic at the call site of the C function:
/** A function that produces your vector */
std::vector<wchar_t> foo();
/** The C function in question */
void theCFunction(wchar_t**);
int main()
{
std::vector<wchar_t> v = foo();
wchar_t* ptr = &v[0];
theCFunction(&ptr);
}
BTW from the question and some comments it sounds like you misunderstand what char and wchar_t are — they sit below the encoding layer and if you have UTF-8 then you should be storing each byte of your UTF-8 string as, well, as a single byte. This means using chars, as in a std::string. Sure, each individual byte in that string will not necessarily represent a single logical unicode character, but then that is not the point of it.
This is the function for converting a vector of std::wstring to a wchar_t** based string. It also won't leak any memory because of using that DisposeBuffer(); call unlike other answers.
wchar_t ** xGramManipulator::GetCConvertedString(vector< wstring> const &input)
{
DisposeBuffer(); //This is to avoid memory leak for calling this function multiple times
cStringArraybuffer = new wchar_t*[input.size()]; //cStringArraybuffer is a member variable of type wchar_t**
for (int i = 0; i < input.size(); i++)
{
cStringArraybuffer[i] = new wchar_t[input[i].size()+1];
wcscpy_s(cStringArraybuffer[i], input[i].size() + 1, input[i].c_str());
cStringArraySize++;
}
return cStringArraybuffer;
}
And this is the DisposeBuffer Helper Function to avoid memory leaks:
void xGramManipulator::DisposeBuffer(void)
{
for (size_t i = 0; i < cStringArraySize; i++)
{
delete [] cStringArraybuffer[i];
}
delete [] cStringArraybuffer;
cStringArraybuffer = nullptr;
cStringArraySize = 0;
}
And prior to these allocate a dummy space in your constructor:
xGramManipulator::xGramManipulator()
{
//allocating dummy array so that when we try to de-allocate it in GetCConvertedString(), dont encounter any undefined behavior
cStringArraybuffer = new wchar_t*[1];
cStringArraySize = 0;
for (int i = 0; i < 1; i++)
{
cStringArraybuffer[i] = new wchar_t[1 + 1];
cStringArraySize++;
}
}
And it's all done.

C++: How to use new to find store for function return value?

I'm reading the 3rd edition of The C++ Programming Language by Bjarne Stroustrup and attempting to complete all the exercises. I'm not sure how to approach exercise 13 from section 6.6, so I thought I'd turn to Stack Overflow for some insight. Here's the description of the problem:
Write a function cat() that takes two C-style string arguments and
returns a single string that is the concatenation of the arguments.
Use new to find store for the result.
Here's my code thus far, with question marks where I'm not sure what to do:
? cat(char first[], char second[])
{
char current = '';
int i = 0;
while (current != '\0')
{
current = first[i];
// somehow append current to whatever will eventually be returned
i++;
}
current = '';
i = 0;
while (current != '\0')
{
current = second[i];
// somehow append current to whatever will eventually be returned
i++;
}
return ?
}
int main(int argc, char* argv[])
{
char first[] = "Hello, ";
char second[] = "World!";
? = cat(first, second);
return 0;
}
And here are my questions:
How do I use new to find store? Am I expected to do something like std::string* result = new std::string; or should I be using new to create another C-style string somehow?
Related to the previous question, what should I return from cat()? I assume it will need to be a pointer if I must use new. But a pointer to what?
Although the problem doesn't mention using delete to free memory, I know I should because I will have used new to allocate. Should I just delete at the end of main, right before returning?
How do I use new to find store? Am I expected to do something like std::string* result = new std::string; or should I be using new to create another C-style string somehow?
The latter; the method takes C-style strings and nothing in the text suggests that it should return anything else. The prototype of the function should thus be char* cat(char const*, char const*). Of course this is not how you’d normally write functions; manual memory management is completely taboo in modern C++ because it’s so error-prone.
Although the problem doesn't mention using delete to free memory, I know I should because I will have used new to allocate. Should I just delete at the end of main, right before returning?
In this exercise, yes. In the real world, no: like I said above, this is completely taboo. In reality you would return a std::string and not allocate memory using new. If you find yourself manually allocating memory (and assuming it’s for good reason), you’d put that memory not in a raw pointer but a smart pointer – std::unique_ptr or std::shared_ptr.
In a "real" program, yes, you would use std::string. It sounds like this example wants you to use a C string instead.
So maybe something like this:
char * cat(char first[], char second[])
{
char *result = new char[strlen(first) + strlen(second) + 1];
...
Q: How do you "append"?
A: Just write everything in "first" to "result".
As soon as you're done, then continue by writing everything in "second" to result (starting where you left off). When you're done, make sure to append '\0' at the end.
You are supposed to return a C style string, so you can't use std::string (or at least, that's not "in the spirit of the question"). Yes, you should use new to make a C-style string.
You should return the C-style string you generated... So, the pointer to the first character of your newly created string.
Correct, you should delete the result at the end. I expect it may be ignored, as in this particular case, it probably doesn't matter that much - but for completeness/correctness, you should.
Here's some old code I dug up from a project of mine a while back:
char* mergeChar(char* text1, char* text2){
//Find the length of the first text
int alen = 0;
while(text1[alen] != '\0')
alen++;
//Find the length of the second text
int blen = 0;
while(text2[blen] != '\0')
blen++;
//Copy the first text
char* newchar = new char[alen + blen + 1];
for(int a = 0; a < alen; a++){
newchar[a] = text1[a];
}
//Copy the second text
for(int b = 0; b < blen; b++)
newchar[alen + b] = text2[b];
//Null terminate!
newchar[alen + blen] = '\0';
return newchar;
}
Generally, in a 'real' program, you'll be expected to use std::string, though. Make sure you delete[] newchar later!
What the exercise means is to use new in order to allocate memory. "Find store" is phrased weirdly, but in fact that's what it does. You tell it how much store you need, it finds an available block of memory that you can use, and returns its address.
It doesn't look like the exercise wants you to use std::string. It sounds like you need to return a char*. So the function prototype should be:
char* cat(const char first[], const char second[]);
Note the const specifier. It's important so that you'll be able to pass string literals as arguments.
So without giving the code out straight away, what you need to do is determine how big the resulting char* string should be, allocate the required amount using new, copy the two source strings into the newly allocated space, and return it.
Note that you normally don't do this kind of memory management manually in C++ (you use std::string instead), but it's still important to know about it, which is why the reason for this exercise.
It seems like you need to use new to allocate memory for a string, and then return the pointer. Therefore the return type of cat would be `char*.
You could do do something like this:
int n = 0;
int k = 0;
//also can use strlen
while( first[n] != '\0' )
n ++ ;
while( second[k] != '\0' )
k ++ ;
//now, the allocation
char* joint = new char[n+k+1]; //+1 for a '\0'
//and for example memcpy for joining
memcpy(joint, first, n );
memcpy(joint+n, second, k+1); //also copying the null
return joint;
It is telling you to do this the C way pretty much:
#include <cstring>
char *cat (const char *s1, const char *s2)
{
// Learn to explore your library a bit, and
// you'll see that there is no need for a loop
// to determine the lengths. Anything C string
// related is in <cstring>.
//
size_t len_s1 = std::strlen(s1);
size_t len_s2 = std::strlen(s2);
char *dst;
// You have the lengths.
// Now use `new` to allocate storage for dst.
/*
* There's a faster way to copy C strings
* than looping, especially when you
* know the lengths...
*
* Use a reference to determine what functions
* in <cstring> COPY values.
* Add code before the return statement to
* do this, and you will have your answer.
*
* Note: remember that C strings are zero
* terminated!
*/
return dst;
}
Don't forget to use the correct operator when you go to free the memory allocated. Otherwise you'll have a memory leak.
Happy coding! :-)

C++ const char* To const char* const

I am currently writing an assignment for my class that is supposed to act as a very basic shell. I am nearly finished, but I am running into an issue with execvp and my character array of parameters. Here is a light snippet of my code.
//Split the left content args
istringstream iss(left);
while(getline(iss, s, ' ')){
v.push_back(s);
}
//Get the split string and put it into array
const char* cmd_left[v.size()+1];
for(unsigned int i = 0; i < v.size(); i++){
cmd_left[i] = v.at(i).c_str();
}
cmd_left[v.size()] = 0;
v.clear();
And this is utilized by...
execvp(cmd_left[0], cmd_left);
My error is
assign3.cxx:96:34: error: invalid conversion from ‘const char**’ to ‘char* const*’ [-fpermissive]
I understand that the problem is that my character array isn't full of constant data, so I need to essentially go from const char* to const char* const. I read something about const_cast, but I wasn't sure if that is what I need to be doing.
If you would be so kind, could you help me get my array of character arrays to be properly accepted by that function? If you need me to post more of my code, let me know.
Thanks
The problem is you cannot pass const variable to function expecting non-const argument.
other word, const char * is a subset of char *.
remove the const
/*const*/ char* cmd_left[v.size()+1];
add const_cast here
cmd_left[i] = const_cast<char *>( v.at(i).c_str() );
other parts of your code look suspicious, but this will make it compile
Without any const_cast:
istringstream iss(left);
while(getline(iss, s, ' ')){
v.push_back(s);
}
//assuming v is not empty! which you were already
string command = v[0]; //store the command in a separate variable (this makes a copy of the string)
char* cmd_left[v.size()+1]; //not a (const char)*
for(unsigned int i = 0; i < v.size(); i++){
cmd_left[i] = new char[v[i].size()+1];
strcpy(cmd_left[i], v[i].c_str()); //copy contents of each string onto a new buffer
}
cmd_left[v.size()] = NULL;
v.clear(); //if you really want to; not necessary from the code you posted
//...
execvp(command.c_str(), cmd_left);
It is not easy, sometimes not possible to create a const dynamic array of elements because all the elements have to declared within the initializer {}.
But luckily you could tell the compiler that the array you are passing is going to be const at least for the certain duration. You could do the following this would yield
&((char* const) (const_cast<char*>(cmd_left[0]) ))
The const_cast inside would remove the const-ness of the array of characters std::string is owning. So, it is quite possible that function might change the contents of array of characters behind the back of std::string. When behaviour of functions taking such argument is known then this might be ok.
If you want to create a const array of char* without resorting to const_cast or managing memory using new/delete, you could use std::vector > instead of vector of strings.
istringstream iss(left);
while(getline(iss, s, ' ')){
v.push_back(std::vector<char>(s.length()+1));
strcpy(&v.back().front(),s.c_str());
}
//Get the split string and put it into array
char* cmd_left[v.size()+1];
for(unsigned int i = 0; i < v.size(); i++){
cmd_left[i] = &v.at(i).front();
}
cmd_left[v.size()] = 0;
v.clear();
execvp(cmd_left[0], &((char* const)cmd_left[0]));
Hope this helps.

Copying C-Style String to Free Store Using Only Dereference

As said in the title, the goal is to copy a C-style string into memory without using any standard library functions or subscripting.
Here is what I have so far [SOLVED]
#include "std_lib_facilities.h"
char* strdup(const char* p)
{
int count = 0;
while (p[count]) ++count;
char* q = new char[count+1];
for (int i = 0; i < count + 1; ++i) *(q + i) = *(p + i);
}
int main()
{
char word[] = "Happy";
char* heap_str = strdup(word);
}
Obviously the problem is that allocating just *p (which is equivalent to p[0]) only allocates the letter "H" to memory. I'm not sure how to go about allocating the C-style string without subscripting or STL functions.
C-style string ends with '\0'. You need to traverse the string inside the function character by character until you encounter '\0' to know how long it is. (This is effectively what you would do by calling strlen() to work it out.) Once you know how long the string is, you can allocate the right amount of memory, which is the length+1 (because of the '\0').
To access the i'th element of an array p, one use subscript: p[i].
Subscript of the form p[i] is formally defined to be *((p)+(i)) by both the C standard (6.5.2.1 of C99) and the C++ standard (5.2.1 of C99). Here, one of p or i is of the type pointer to T, and the other is of integral type (or enumeration in C++). Because array name is converted automatically (in most types of use anyway) to a pointer to the first element of said array, p[i] is thus the i'th element of array p.
And just like basic arithmetic, ((p)+(i)) is equivalent to ((i)+(p)) in pointer arithmetic. This mean *((p)+(i)) is equivalent to *((i)+(p)). Which also mean p[i] is equivalent to i[p].
Well, since this a self-teaching exercise, here's an alternative look at a solution that can be compared/contrasted with KTC's nice explanation of the equivalence between subscripting and pointer arithmetic.
The problem appears to be, "implement a strdup() function without using standard library facilities or subscripting".
I'm going to make an exception for malloc(), as there's no reasonable way to do the above without it, and I think that using it isn't detrimental to what's being taught.
First, let's do a basic implementation of strdup(), calling functions that are similar to the ones we might use from the library:
size_t myStrlen( char* s);
void myStrcpy( char* dst, char* src);
char* strdup( char* p)
{
size_t len = myStrlen( p);
char* dup = (char*) malloc( len + 1); /* include space for the termination character */
if (dup) {
myStrcpy( dup, p);
}
return dup;
}
Now lets implement the worker functions without subscripting:
size_t myStrlen( char* s)
{
size_t len = 0;
while (*s != '\0') { /* when s points to a '\0' character, we're at the end of the string */
len += 1;
s += 1; /* move the pointer to the next character */
}
return len;
}
void myStrcpy( char* dst, char* src)
{
while (*src != '\0') { /* when src points to a '\0' character, we're at the end of the string */
*dst = *src;
++dst; /* move both pointers to next character location */
++src;
}
*dst = '\0'; /* make sure the destination string is properly terminated */
}
And there you have it. I think this satisfies the condition of the assignment and shows how pointers can be manipulated to move though an array of data items instead of using subscripting. Of course, the logic for the myStrlen() and myStrcpy() routines can be moved inline if desired, and more idiomatic expressions where the pointer increment can happen in the expression that copies the data can be used (but I think that's more confusing for beginners).

Dealing with char arrays in C++

I have this C-styled piece of initialization code:
const char * const vlc_args[] =
{
"-I", "dummy",
"--ignore-config",
"--extraintf=logger",
"--verbose=2"
"--plugin-path=/usr/lib/vlc"
};
//tricky calculation of the char space used
libvlc_new(sizeof(vlc_args)/sizeof(vlc_args[0]), vlc_args, &exc);
Since I need to make the --plugin-path parameter dynamic, I can't use a static array anymore. So I came up with a C++ alternative:
std::string pluginpath = "test";
libvlc_exception_t exc;
std::vector<std::string> args;
args.push_back("-I");
args.push_back("dummy");
args.push_back("--ignore-config");
args.push_back("--extraintf=logger");
args.push_back("--verbose=2");
args.push_back("--ipv4");
args.push_back("--plugin-path=" + pluginpath);
std::string combinedString;
for (size_t idx = 0; idx < args.size(); ++idx)
{
combinedString.append(args[idx]);
combinedString.resize(combinedString.size() + 1);
combinedString[combinedString.size() - 1] = 0;
}
combinedString.resize(combinedString.size() + 1);
combinedString[combinedString.size() - 1] = 0;
size_t size = combinedString.size();
const char * data = combinedString.c_str();
libvlc_new(size, &data, &exc); // => error occurs here (not at end of scope or anything)
But this results in a segmentation fault. So there must be an error in my code, which I can't seem to find.. Can anyone spot it?
Solved!
Thanks to Joseph Grahn and Jason Orendorff. My idea on the memory layout of the C-style array was wrong. I thought all data was organized as a big sequential block. In reality it's a list of pointers to the first character of each individual string.
This code works:
std::vector<const char*> charArgs;
for (size_t idx = 0; idx < args.size(); ++idx)
{
charArgs.push_back(&(args[idx][0]));
}
mVLCInstance = libvlc_new(charArgs.size(),
&charArgs[0],
&mVLCException);
I think Josef Grahn is right: the API wants an actual array of pointers.
If you don't need to add arguments programmatically, you can just go back to using an array:
std::string pluginpath = "test";
std::string pluginpath_arg = "--plugin-path=" + pluginpath;
const char *args[] = {
"-I", dummy, "--ignore-config", ..., pluginpath_arg.c_str()
};
libvlc_exception_t exc;
libvlc_new(sizeof(args) / sizeof(args[0]), args, &exc);
EDIT: There might also be a problem with using c_str() here. This is true if VLC keeps the pointer and uses it again later; I can't tell if that's the case from the docs.
You are appending all arguments into a single string, then you pass a pointer to the const char * string to libvlc_new as if it were an array of char *.
(I'm not sure this is the problem, but it seems a bit strange.)
Have you tried:
libvlc_new(size, data, &exc);
instead of
libvlc_new(size, &data, &exc);
It seems you use the null bytes to make the string act like an array of characters, but then you pass a pointer to the char* "array" instead of just the array.
The library call expects a pointer to an array of const char* (that is several pointers), but you pass it a single pointer. That more characters got appended to the end of that string doesn't matter.
To dynamically build an array of the required pointers you could use another vector:
// store c_str() pointers in vector
std::vector<const char*> combined;
for (size_t idx = 0; idx < args.size(); ++idx) {
combined.push_back(args[idx].c_str());
}
// pass pointer to begin of array (it is guaranteed that the contents of a vector
// are stored in a continuous memory area)
libvlc_new(combined.size(), &(combined[0]), &exc);
Jason Orendorff's remark is also valid here: This will not work if libvlc_new stores the passed pointer internally for later use.
Regarding the segmentation violation
No solution, as there will probably be more problems
You are sending only 1 string in. (not sure if it is allowed by libvlc_new) So the first parameter should be set to 1, ie size = 1. I believe this will solve the segmentation problem. But I doubt libvlc_new can be called with just one line of multiple parameters.
In the original code sizeof(vlc_args)/sizeof(vlc_args[0]) will have the number of parameters as entries in the vector. In your example equal 6.
Your code
size_t size = combinedString.size(); // a long string, size >> 1
const char * data = combinedString.c_str(); // data is a pointer to the string
libvlc_new(size, &data, &exc);
// size should be 1 because data is like an array with only one string.
// &data is the adress to the "array" so to speak. If size > 1 the function
// will try to read pass the only string available in this "array"
I think Jason Orendorff has a good solution to fix it all...
I had this same issue; I wanted to dynamicly generate the arguments, but in a safe c++ way.
The solution I hit on was to use the unique_ptr<[]> new to C++ 11. For example:
unique_ptr<char *[]> vlc_argv;
int vlc_argc;
...
auto vlc(libvlc_new(vlc_argc, vlc_argv.get()));
This gives me a nice RAII object to hold my arguments in that I can still pass into libvlc_new(). Since the arguments are raw pointers in argv, managed by the OS, we can just use those in our vlc_argv directly.
As a further example assume I process the first few args out of argv (somewhere in the "..." area above), and want to pass everything from next_arg on to libvlc_new():
vlc_argv = std::unique_ptr<char *[]>(new char *[2 + argc - next_arg]);
vlc_argv[0] = argv[0];
for (vlc_argc=1; vlc_argc <= argc - next_arg; vlc_argc++) {
vlc_argv[vlc_argc] = argv[next_arg + vlc_argc - 1];
}
vlc_argv[vlc_argc] = 0;
The problem is due to the use of c_str() and storing the pointer.
See stringstream, string, and char* conversion confusion
EDIT Forget what I said... it was late... see the comments :)