C++ writing to std::string* var from file [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Actually I'm experiencing a problem with saving single char to string*. I've got a function like this:
void save(std::string* x, const std::string& file);
Actually I'm taking each digit from the file using loop and assign it to char ch;
So, the question is how can I append this char to string*? If I make temp string and add each symbol to this string and after just do strcpy or just x = temp, I'm getting segmentation fault.
Would you tell me how to deal with this?
Thank you.

You should never directly alter a std::string's buffer, because it has its own method of managing the memory.
Instead, you should use the append() method:
char temp;
//...
if(x) //check for nullptr
{
x->append(1, temp); //appends the char 'temp' once
}

It sounds like you're creating a local string and then assigning it to x - something like this:
std::string temp;
// Add to temp
// ...
x = &temp;
The problem with this is that x is effectively an out parameter and you're assigning it to a local. When the function goes out of scope the local (temp) will be destroyed, and x will now point to the destroyed region of memory. This will give you an access violation.
You're best bet is change save so that it returns the string. Something like this:
std::string save(const std::string &file)
{
std::string temp;
// Do stuff...
return temp;
}
Now the string will be correctly copied (or moved if you're C++11) back to the caller. You can use push_back to append characters to temp.
If you don't want to return the string then pass a reference to a user supplied string and fill that:
void save(std::string &x, const std::string &file)
{
char temp;
x.push_back(temp);
}
and then call it like this:
std::string output;
save(output, "path/to/my/file);

Related

(Seg Fault) Read a text file line by line into char double pointer using realloc [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am trying to read multiple parameters from a .txt file into a char**. Each line of the text file contains a parameter.
I wrote the following code but somehow run into seg fault error. I identified the error probably to be the line
argv[n_lines - 1] = const_cast<char*>(para.c_str());
where I am tring to assign the parameter (c string) to the slots of char**. Somehow, I am not allowed to access the spot.
Can anyone point out what I did wrong and how I can correct the mistake?
#include <iostream>
#include <fstream> // Use ifstream
char** file_to_argv(const char* filename) {
std::string line;
char** argv = NULL;
int n_lines = 0; // Number of parameters in total
std::ifstream file(filename); // read the entire file
std::string para; // parameter <-> each line in file
while (std::getline(file, para)) { // Keep reading in each parameter
argv = (char**)realloc(argv, sizeof(char*) * ++n_lines);
/* Check if enough memory is available */
if (argv = NULL)
exit(-1); // memory allocation fails
// Store parameter into argv array
argv[n_lines - 1] = const_cast<char*>(para.c_str());
}
/* Reallocate one extra slot for the last NULL so that argv is null
terminated, which is a good identifier when looping */
argv = (char**)realloc(argv, sizeof(char*) * (n_lines + 1));
return argv;
}
int main() {
char** argv = file_to_argv("parameters.txt");
int i = 0;
// print out all parameters line by line in the text file
while (argv[i] != NULL) {
printf("res[%d] = %s\n", i, argv[i]);
i++;
}
delete argv;
return 0;
}
argv[n_lines - 1] = const_cast<char*>(para.c_str());
Casting away const-ness is already undefined behavior territory. So, this is already broken. But that's not even the major problem. The pointer returned by c_str() is owned by std::string, and is no longer valid after any subsequent modification to the std::string. But what does your code do next?
while (std::getline(file, para)) {
It immediately reads the next line into para. The previously-returned c_str() is no longer valid, and dereferencing it from that point is guaranteed undefined behavior, and your likely crash.
Your apparent goal is to construct a C-compatible argv-style array. The approach that I've used in the past, that doesn't break any rules, is to construct a
std::vector<std::vector<char>> argv;
Then have my code meticulously create each string, and explicitly \0 terminate it. Then to construct the final C-style argv I simply grab the pointer to the first character of each vector, and use it to construct a
std::vector<char *> c_argv;
This does not break any rules. No tim needs to be wasted on awkward and error-prone malloc or realloc calls. The vector correctly manages all my memory for me. This is what vectors are for.

Assigning string* to char* c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to read a file in c++ and save every line(in a vector) as i will be processing them later.
I also need to save a vector of char* that will point to the first position of each string*.
The problem is that I don't know how to assign the string* to char*.
FYI, i can not use const char*, it has to be char*.
Code:
void ClassA::readFile() {
std::ifstream file("test.txt");
std::string* str = new string();
while (std::getline(file, *str))
{
_aVector.push_back(*str);
char *c = &str[0]; <-- This works if string is not declared as string*
char *c = .... <--What is the equivalent for string*
str = new string();
someFunction(c); <-- This function saves the *c in a vector.
}
}
Though the std::string protocol gives you access to the underlying memory, e.g. by calling member c_str(), these pointers are all const. If you cast it to a non-const pointer, you risk undefined behaviour if a function beyond your control then modifies the content through such a pointer.
Since C++17, the data-method gives you access to a non-const pointer to the underlying data.
Anyway, note that a string-object will - again beyond your control - replace the underlying memory if necessary, and your pointers might become invalid then. So I'd say that it's generally not a good idea to store pointers to the contents of string objects.
The only way to get a char*-pointer to the contents of an std::string I see is to copy the contents of the string, e.g. by using strdup. Thereby you avoid undefined behaviour from unintended modifying access, and you decouple the char* from the memory managed by the string object.
See the following code illustrating this:
int main() {
std::vector<std::string> aVector;
std::ifstream file("test.txt");
std::string str;
while (std::getline(file, str))
{
aVector.push_back(str);
char *c = strdup(str.c_str());
someFunction(c); // <-- This function saves the *c in a vector.
}
}

cpp-how to get only the value of c_str() [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a function which return const char*.
In this function I have the following params:
string str;
For converting str to const char* I use str.c_str().
When I debug I notice that str.c_str() contains something (I guess its address) before the value of the string.
For example:
If str="0"
I str.c_str() wiil 0x68d5f9 "0".
Why is it?
How can I get only the value of the string?
This is not a problem, this is how pointers work.
Pointers point to data contained at some memory address and the debugger shows you that this pointer points to address 0x<something> and the value at this address is '0'. Nothing odd here.
When you print this value you got from str.c_str(), you'll get an ordinary C string.
cout << str.c_str();
This will give you the same as cout << str;
You wouldn't get the address pointed to by the pointer in the string returned by c_str. It is a debugger artifact designed to let programmers inspect the address along with the value.
However, returning the result of c_str may be undefined behavior if the call is made on a function-scoped string.
For example, this is illegal:
const char *illegal_return() {
string s = "quick brown fox";
return s.c_str(); // <<== Return of c_str from a local string
}
The best fix is to return a string. If you would like to return a char pointer instead, you need to make a copy:
char *legal_return() {
string s = "quick brown fox";
const char *ptr = s.c_str();
size_t len = strlen(ptr);
char *res = new char[len+1];
strcpy(res, ptr);
return res;
}
The caller of the above function must call delete[] on the result to avoid memory leaks.

How do I pass an std::string to a function that expects char*? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can I get a non-const C string back from a C++ string?
Do I need to convert it first? I saw in another post that .c_str() can be used if the function expected const char*. What about for just char*?
std::vector<char> buffer(s.begin(), s.end());
foo(&buffer[0], buffer.size());
s.assign(buffer.begin(), buffer.end());
There is no way to get a char* from a string that is guaranteed to work on all platforms, for the simple fact that string is not required to use contiguous storage.
Your safest, most portable course of action is to copy the string somewhere that does use contigious storage (a vector perhaps), and use that instead.
vector<char> chars(my_string.begin(), my_string.end());
char* ptr = &chars[0];
If you want to be hacky and non-portable and decidedly unsafe, you can confirm that your string implementation does in fact use contigious storage, and then maybe use this:
&my_str[0]
But I would punch any developer that worked for me that did this.
EDIT:
I've been made aware that there are currently no known STL implementations that do not store the string data in a contiguous array, which would make &my_str[0] safe. It is also true (and I was asked to state this) that in the upcoming C++0x standard, it will be required for the storage to be contiguous.
It's been suggested that because if these facts that my post is factually incorrect.
Decide for yourself, but I say no. This is not in the current C++ standard, and so it is not required. I will still in practice do things the way I have suggested, and in any code review I will flag any code that assumes the underlying storage is contigious.
Consider this. Suppose there were a question about vtable pointers. Someone wants to examing a class and get the pointer to a virtual function by looking at the vtable. I would immediately tell them not to do this because there is no mention of how virtual methods are implemented in C++. Every implementation I know uses vtables, and I can't think of a better way to do it. It is likely that polymorphism will forever be implemented using vtables. Does that make it ok to examing the vtable directly?
IMO no, because this depends on undocumented implementation details. You have no control over this, and it could change at any time. Even if you expect it will never change, it is still bad engineering to rely on these implementation details.
Decide for yourself.
There are three scenarios:
If the function is outside of your control, and it either modifies the string, or you don't and can't know if it modifies the string:
Then, copy the string into a temporary buffer, and pass that to the function, like so:
void callFoo(std::string& str);
{
char* tmp = new char str(str.length() +1);
strncpy(tmp, str.c_str(), str.length());
foo(tmp);
// Include the following line if you want the modified value:
str = tmp;
delete [] tmp;
}
If the function is outside of your control, but you are certain it does not modify the string, and that not taking the argument as const is simply a mistake on the API's part.
Then, you can cast the const away and pass that to the function
void callFoo(const std::string& str)
{
foo(const_cast<char*> str.c_str());
}
You are in control of the function (and it would not be overly disruptive to change the signature).
In that case, change the function to accept either a string& (if it modifies the input buffer) or either const char* or const string& if it does not.
When a parameter is declared as char* there it is implicitly assumed that the function will have as a side effect the modification of the string that is pointed. Based in this and the fact that c_str() does not allow modifications to the enclosed string you cannot explicitly pass an std::string to such a method.
Something like this can be achived by following the following approach:
#include <cstdlib>
#include <string>
#include <iostream>
void modify_string(char* pz)
{
pz[0] = 'm';
}
class string_wrapper
{
std::string& _s;
char* _psz;
string_wrapper(const string_wrapper&);
string_wrapper& operator=(const string_wrapper&);
public:
string_wrapper(std::string& s) : _s(s), _psz(0) {}
virtual ~string_wrapper()
{
if(0 != _psz)
{
_s = _psz;
delete[] _psz;
}
}
operator char*()
{
_psz = new char[_s.length()+1];
strcpy(_psz,_s.c_str());
return _psz;
}
};
int main(int argc, char** argv)
{
using namespace std;
std::string s("This is a test");
cout << s << endl;
modify_string(string_wrapper(s));
cout << s << endl;
return 0;
}
If you are certain that the char* will not be modified, you can use const_cast to remove the const.
It's a dirty solution but I guess it works
std::string foo("example");
char* cpy = (char*)malloc(foo.size()+1);
memcpy(cpy, foo.c_str(), foo.size()+1);

C++ new & delete and string & functions

Okay the previous question was answered clearly, but i found out another problem.
What if I do:
char *test(int ran){
char *ret = new char[ran];
// process...
return ret;
}
And then run it:
for(int i = 0; i < 100000000; i++){
string str = test(rand()%10000000+10000000);
// process...
// no need to delete str anymore? string destructor does it for me here?
}
So after converting the char* to string, I don't have to worry about the deleting anymore?
Edit: As answered, I have to delete[] each new[] call, but on my case its not possible since the pointer got lost, so the question is: how do I convert char to string properly?
Here you are not converting the char* to a [std::]string, but copying the char* to a [std::]string.
As a rule of thumb, for every new there should be a delete.
In this case, you'll need to store a copy of the pointer and delete it when you're done:
char* temp = test(rand()%10000000+10000000);
string str = temp;
delete[] temp;
You seem to be under the impresison that passing a char* into std::string transfers ownership of the allocated memory. In fact it just makes a copy.
The easiest way to solve this is to just use a std::string throughout the entire function and return it directly.
std::string test(int ran){
std::string ret;
ret.resize(ran - 1); // If accessing by individual character, or not if using the entire string at once.
// process... (omit adding the null terminator)
return ret;
}
Yes, yes you do.
If you are using linux/os x, look into something like valgrind which can help you with memory issues
You can change your test function so that it returns a string instead of char *, this way you can delete [] ret in the test function.
OR you could just use a string in test as well and not have to worry about new/delete.
You must call delete for every new otherwise you will leak memory. In the case you have shown you are throwing away the pointer, if you must leave the function as returning a char* then you will need to use two lines to create the std::string so you can retain a copy of the char* to delete.
A better solution would be to rewrite your test() function to return a std::string directly.
You need to do something like this:
for(int i = 0; i < 100000000; i++){
int length = rand()%10000000+10000000;
char* tmp = test(length);
string str(tmp);
delete[length] tmp;
}
This deletes the allocated char-array properly.
By the way, you should always zero-terminate a string if you create it this way (i.e. inside the function test), otherwise some functions can easily get "confused" and treat data behind your string as part of it, which in the best case crashes your application, and in the worst case creating a silent buffer overflow leading to undefined behaviour at a later point, which is the ultimate debugging nightmare... ;)