Converting vector<string> to char** results in segmentation fault - c++

I am a absolutely begginer in C++ but i have an assignent. I have to convert a vector to char** to use it in execvp. So i wrote this test which is building ok but when i run it i get segmentation fault instead of "First". I am bad at pointer and i would like your help. Thanks
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
int main()
{
vector<string>* list = new vector<string>();
list->push_back("First");
list->push_back("Second");
list->push_back("Third");
char ** arr;
arr[0] = strdup(list->at(0).c_str());
cout << arr[0] << endl;
return 0;
}
EDIT 1
Ok here's the actual problem. The Command::getCommandArray() seems to work as expected but when i call it from main and try to display the arr[0] it results in segmentation fault again. Why?
// Command.cpp
char** Command::getCommandArray()
{
int i=0;
int len = args->size() + 2;
char* arr[len];
arr[0] = strdup(this->commandName->c_str());
arr[len-1] = NULL;
for (i=0; i<this->args->size(); i++)
{
arr[i+1] = strdup(this->args->at(i).c_str());
}
cout << "in: " << arr[0] << endl; // PRINTS AS EXPECTED
return arr;
}
// main.cpp
do {
char** arr = tmp->getCommandArray();
cout << arr[0] << endl; // SEGMENTATION FAULT HERE
} while((tmp = tmp->getPipeline()) != NULL);
EDIT 2 Ok i solved it. Thank you very much!
I had to change line
char* arr[len];
to
char** arr = new char*[len];

I see no reason to duplicate strings here, or to manually manage memory. You can just use another vector to store the char pointers, and get a pointer to that vector's memory.
int main()
{
std::vector<std::string> list;
list.push_back("First");
list.push_back("Second");
list.push_back("Third");
std::vector<char*> ptr_list;
for (std::size_t i = 0; i != list.size(); ++i) {
ptr_list.push_back(&list.at(i)[0]);
}
char** arr = &ptr_list[0];
std::cout << arr[0] << std::endl;
}

It should be something like:
int main()
{
std::vector<std::string> list;
list.push_back("First");
list.push_back("Second");
list.push_back("Third");
char** arr = new char*[list.size()];
for (std::size_t i = 0; i != list.size(); ++i) {
arr[i] = strdup(list.at(i).c_str());
}
std::cout << arr[0] << std::endl;
for (std::size_t i = 0; i != list.size(); ++i) {
free(arr[i]);
}
delete[] arr;
}

Note that the argv and envp arrays you pass in to execve() need to be null terminated (in addition to the strings in those arrays):
char ** convert(std::vector<std::string> v)
{
char ** t = new char* [v.size() + 1];
// Need this for execve
t[v.size()] = nullptr;
for (int i = 0 ; i < v.size(); ++i)
{
t[i] = strdup(v[i].c_str());
}
return t;
}

Related

C++ program behavior on pointers to integer array

Can anyone please explain why the loop only execute once!!
The for loop executes once and never reaches end of the programm
and if you've got some time to review my mistakes then please point out mistakes because i know this is not how it is done!!
using namespace std;
#include<iostream>
int* rotate(int* ar,int d,int n)
{
int tmp[n];
d = d%n;
for (int i = 0; i < n; ++i)
{
tmp[i] = ar[(i+d)%n];
}
free(ar);
return tmp;
}
int main(int argc, char const *argv[])
{
int arr[] = {1,2,3,4,5};
int *a;
int n = sizeof(arr)/sizeof(arr[0]);
a = rotate(arr,4,n);
cout<<endl;
for (int i = 0; i < n; ++i)
{
cout<<i<<endl;
cout<<a[i]<<endl;
}
cout<<"End";
return 0;
}
Lets take it apart...
int* rotate(int* ar,int d,int n)
{
int tmp[n]; // 1
d = d%n;
for (int i = 0; i < n; ++i)
{
tmp[i] = ar[(i+d)%n];
}
free(ar); // 2
return tmp; // 3
}
int tmp[n]; is not standard C++. If you do not want to use std::vector the proper replacement would be a dynamically allocated array.
You call free with a pointer that was not allocated via malloc, which invokes undefined behavior. In C++ you shouldn't be using free and malloc at all, but rather new and delete. And also new and delete only for such exercise. Otherwise use smart pointers.
You return a pointer to a local variable. The pointer is dangling and using it in main invokes undefined behavior.
You can't simply replace the static array arr in main with something else in the function. A function called rotate is not expected to create a new array or delete the one that was passed (also because like in your case it is just not possible).
There are different ways to fix your code. I choose to make rotate rotate the array "in-place". However, as you can see, the implementation actually uses an additional array of same size. I leave it to you to figure out how to change it to use less additional memory:
#include <iostream>
using std::cout;
using std::endl;
void rotate(int* ar,int d,int n)
{
int* tmp = new int[n];
d = d%n;
for (int i = 0; i < n; ++i)
{
tmp[i] = ar[(i+d)%n];
}
for (int i = 0; i < n; ++i)
{
ar[i] = tmp[i];
}
}
int main(int argc, char const *argv[])
{
int arr[] = {1,2,3,4,5};
int n = sizeof(arr)/sizeof(arr[0]);
rotate(arr,4,n);
cout<<endl;
for (int i = 0; i < n; ++i)
{
cout<<i<<endl;
cout<<arr[i]<<endl;
}
cout<<"End";
return 0;
}
This is how you can do the same using std::rotate:
#include <array>
#include <iostream>
#include <algorithm>
int main(int argc, char const *argv[])
{
int arr[] = {1,2,3,4,5};
int n = sizeof(arr)/sizeof(arr[0]);
std::rotate(std::begin(arr),std::begin(arr)+4,std::end(arr));
for (int i = 0; i < n; ++i)
{
std::cout << i << std::endl;
std::cout << arr[i] << std::endl;
}
std::cout<<"End";
}
... it even uses pointers ;)

Passing C++ String to C libraries for memory management

I am trying to use a C Library, which requires that I pass in dynamically allocated c-strings for the functions to modify. However, I want to avoid using new/delete operators because I feel it is better practice to have memory management done under the hood by STL libraries, rather than by me.
Below, I'm trying to use std::string (and vectors) to solve this problem, and preallocating them before passing them to the C function. The examples with one string (CChar, CVoid) work, but I'm still unsure if this is the correct way, or even if it is a safe way (bug-free) to do it. Using vectors does not seem to work at all.
I have included the "C"-way of doing what I want to achieve for both strings and vectors.
#include <string>
#include <iostream>
#include <vector>
// ----------------------------------------------------
// Example C library Code
void CChar(char* data, int len)
{
int i;
for (i = 0; i < len; ++i)
data[i] = 'A' + (i % 26);
}
void CVoid(void* data, int len)
{
char* d = (char*)data;
int i;
for (i = 0; i < len; ++i)
d[i] = 'Z' - (i % 26);
}
void CStrings(char** strings, int count, int lengths)
{
int i, j;
for (i = 0; i < count; ++i)
for (j = 0; j < lengths; ++j)
strings[i][j] = 'A' + ((i * j + i) % 26);
}
// ----------------------------------------------------
// C++ code
int main()
{
// Traditional way, using new/delete.
char* c = new char[11];
CChar(c, 10);
c[10] = '\0';
std::cout << c << std::endl; // ABCDEFGHIJ
delete [] c;
std::string s(10, '\0');
CChar(&s[0], 10);
std::cout << s << std::endl; // ABCDEFGHIJ
CVoid(&s[0], 10);
std::cout << s << std::endl; // ZYXWVUTSRQ
std::vector<std::string> v(5, std::string(10, '\0'));
// Traditional way with arrays of arrays.
char** cc = new char*[5];
for (int i = 0; i < 5; ++i)
{
cc[i] = new char[11];
cc[i][10] = '\0';
}
CStrings(cc, 5, 10);
for (int i = 0; i < 5; ++i)
{
std::cout << cc[i] << std::endl; // AAAAAAAAAA, BCDEFGHIJK, CEGIKMOQSU, DGJMPSVYBE, EIMQUYCGKO
delete [] cc[i];
}
delete [] cc;
// Doesn't compile
// CStrings(&v[0], 5, 10);
// for (int i = 0; i < 5; ++i)
// std::cout << v[i] << std::endl;
return 0;
}
Summary: Is there a good way to use C++'s STL libraries so that I don't need to do my own resource management when trying to use C libraries.
edit: Error cleaning up array of arrays
Sure, you can just use std::vector<char> is you don't want to think about allocation. Here's how you do it:
#include <vector>
int main()
{
std::vector<char> str(100, 0); //Allocate an array of 100 chars and initialize them to 0
SomeFunction(&str[0], str.size()); //Pass the address to the array and its size
return 0;
}
For arrays of arrays, can store a vector<char*> which refers to the starts of the already dynamically allocated std::vector<std::string>.
int main()
{
std::vector<std::string> v(5, std::string(10, '\0'));
std::vector<char*> vc(5);
for (int i = 0; i < 5; ++i)
vc[i] = &(v[i])[0];
CStrings(&vc[0], 5, 10);
for (int i = 0; i < 5; ++i)
std::cout << v[i] << std::endl;
return 0;
}

initializing vector of char * does crazy things to my computer

I am trying to solve this puzzle: http://www.puzzleup.com/2015/puzzle/?13
to do that, I want to calculate all the possible codes and pass them in a vector
You will produce a set of 7-letter codes using the the letters A, B,
C, D, E, F and G
So I tried to create vector of char arrays. The code is shared below:
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <cmath>
char letters[] = {'a','b','c','d','e','f','g'};
char * tempArr;
char * pastArr;
std::vector<char * > deneme;
char s1[] = {'a', 'b'};
char s2[] = {'c', 'd'};
void calculateAllPossibilities(int depth, int lastDepth)
{
//depth 1 den baĆ¾layacak
for( int i = 0; i < sizeof(letters); i++ )
{
//
if ( depth != 1 && depth != lastDepth )
{
//
tempArr = new char[depth];
for( int j = 0; j < depth-1; j++ )
{
//
*tempArr = pastArr[j];
tempArr++;
}
*tempArr = letters[i];
for( int x = 0; x < depth; x++ )
{
//
std::cout << tempArr[x] << ",";
}
std::cout << std::endl;
delete pastArr;
pastArr = new char[depth];
for( int k = 0; k < depth; k++ )
{
//
*pastArr = tempArr[k];
pastArr++;
}
delete tempArr;
calculateAllPossibilities(depth + 1, lastDepth );
}
else if( depth == lastDepth )
{
//
tempArr = new char[depth];
for( int k = 0; k < depth - 1; k++ )
{
//
*tempArr = pastArr[k];
tempArr++;
}
*tempArr = letters[i];
for( int x = 0; x < depth; x++ )
{
//
std::cout << tempArr[x] << ",";
}
std::cout << std::endl;
deneme.push_back(tempArr);
delete tempArr;
}
else if( depth == 1 )
{
//
pastArr = new char[depth];
*pastArr = letters[i];
std::cout << pastArr[0] << std::endl;
delete tempArr;
calculateAllPossibilities(depth + 1, lastDepth );
}
}
}
int main()
{
calculateAllPossibilities(1,7);
std::cout << deneme[0][2];
return 0;
}
The problem is, when I try to cout the values of deneme vector without using cout in functions, it gives me different thing in each compilation. Like those: ":", "_", "X", "2" :)
However, then I added couts to function and tried to see whats going on and BAM! My computer goes crazy after couts!
What am I doing wrong here? First time I encountered something like this.
This is not going to work, at all
deneme.push_back(tempArr);
delete tempArr;
You save a pointer to an array in the vector, and then you delete the array. Now the saved pointer points nowhere.
It would work much better with a vector of std::string.
Also, when you allocate an array with tempArr = new char[depth];, the [] should also be used when deleting, like delete[] tempArray. That lets the compiler know that you are deleting an array, and not just one char. Not that it matters too much here.

Seg fault is eliminated when copying char** -- why is this?

class uid
{
public:
char id[6] = {'0','0','0','0','0','0'};
uid() {}
~uid() {}
inline void recursive(int x)
{
if(':' == id[x])
{
id[x] = '0';
++id[--x];
recursive(x);
}
}
char* operator++()
{
++id[5];
recursive(5);
return id;
}
void write(char* pchar) const
{
for(int i = 0; i < 6; ++i)
pchar[i] = id[i];
}
};
using namespace std;
int main(int argc, char** argv)
{
const int MAX = 5000000;
uid c;
char** arr = new char*[MAX];
//char** it = arr;
//loop 1
for(int i = 0; i < MAX; ++i)
arr[i] = new char[6];
cout << "allocated" << endl;
//loop 2
for(int i = 0; i < MAX; ++i)
{
++c;
c.write(arr[i]);
}
cout << "data written" << endl;
for(int i = 0; i < MAX; ++i)
delete[] arr[i];
cout << "deleting arr" << endl;
delete[] arr;
return 0;
}
Running this will cause a seg fault in loop 2 when i == 999999 -- However, when adding the line:
char** it = arr;
The seg fault disappears -- does anyone have any ideas of why this happens?
Thanks
As soon as you go past 999,999 you are writing to memory not owned by c. Declaring it changes the memory map enough that there is no immediate segfault, but the code is still not correct, and any other small change might bring back the fault.
Here's how to fix it:
inline void recursive(int x)
{
if(':' == id[x])
{
id[x] = '0';
if (x) { // <-- added this
++id[--x];
recursive(x);
}
}
}
Now overflow will wrap around to 000000 instead of creating a 7 digit number in a space not big enough to hold it.

C++ char** -> vector<string> -> string -> char** parsing problem

Lets say that I'm trying to solve a parsing problem of string to char **
For some reason the below code generates a lot of trash, can anyone have a look at it please?
Here's what it's supposed to do :
Dump all argv into a string_array
container
Dump everything in the string_array
container into a std::string and
separate with spaces
Break the string down into string
tokens using boost/algorithm/string
create a new char ** and dump all
tokens into it, print out the new char **, clean up
What have I done wrong ?
#include <string>
#include <vector>
#include <iostream>
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
typedef vector<string> string_array;
int main(int argc, char ** argv)
{
string_array args;
string_array tokens;
cout << "Real arguments :" << endl;
for(int i = 0; i < argc; i++)
{ cout << argv[i] << endl;}
string arg = "";
for(int i = 1; i < argc; i++)
{
args.push_back(argv[i]);
}
for(int i = 0; i < (int)args.size(); i++)
{
arg += args[i];
if(i != (int)args.size() - 1)
arg += " ";
}
split(tokens, arg, is_any_of(" "));
char ** new_args = NULL;
new_args = new char*[(int)tokens.size()];
for(int i = 0; i < (int)tokens.size(); i++)
{
new_args[i] = new char[(int)tokens[i].size()];
for(int j = 0; j < (int)tokens[i].size(); j++)
{
new_args[i][j] = tokens[i][j];
}
}
for(int i = 0; i < (int)tokens.size(); i++)
{ std::cout << new_args[i] << std::endl; }
delete [] new_args;
}
C-style strings (char*) are meant to be zero-terminated. So instead of new char[tokens[i].size()], you need to add 1 to the allocation: new char[token[i].size() + 1]. Also, you need to set new_args[i][tokens[i].size()] = 0 to zero-terminate the string.
Without the zero-terminator, programs would not know when to stop printing, as char* does not hold a string length, unlike std::string.