-1

I have a function like this:

template <typename T>
void parse_to_T(const std::string& str, T* result) {
    std::stringstream ss;
    ss << str;
    ss >> *result;
}

this function is mean to convert the string to the specified type.

it is work to parse the string to int, float or char.

parse_to_T<int>(...);
parse_to_T<float>(...);
parse_to_T<char>(...);

but when meet char*, segment fault ...

I use the function like this:

int int_val;
string m = "1";
parse_to_T<int>(m, &int_val); // works
char* str_val = NULL;
parse_to_T<char*>(m, &str_val); // segmentfault

How to imply this function to make it work?

(convert the string to specified type like int, double, char, char*)?

Hey, I don't know how to explain my use case, but I will try:

To simple, the question is, given a file, for each line, data may have these types :

  • int
  • float
  • char
  • char*
  • an array T[num] (T is int, float, char or char*, or any build_in type.)

imple a parse function to parse this file.

and this problem is an exam ...


thanks and I found the error now.

char* str_val = NULL;
parse_to_T<char*>(m, &str_val); // segmentfault;
char* str_val;
parse_to_T<char*>(m, &str_val); // segmentfault;
char* str_val = new char[256];
parse_to_T<char*>(m, &str_val); // works !!

then the error is I didn't allocate memory to the ptr...

李浩然
  • 243
  • 1
  • 3
  • 9
  • You're dereferencing an uninitialized pointer – Tas Feb 28 '17 at 05:24
  • I don't suppose you would find functions like the [`std::stod`](http://en.cppreference.com/w/cpp/string/basic_string/stof) and [`std::stoi`](http://en.cppreference.com/w/cpp/string/basic_string/stol) families more appealing? It seems to me you're trying to reinvent a wheel here. – WhozCraig Feb 28 '17 at 05:27
  • @Tas sorry.. I just forget to type it to the question. – 李浩然 Feb 28 '17 at 05:30
  • @WhozCraig I really know this function works. But my problem is to imple a common function to convert it to specified type.......... – 李浩然 Feb 28 '17 at 05:31
  • 3
    Your question really just doesn't make any sense. Why would you want to convert a string to a char* using stringstream? What possible use case could there be for that? – David Schwartz Feb 28 '17 at 05:35
  • Don't use `char*`. – n. m. could be an AI Feb 28 '17 at 05:39
  • Replace `char* str_val = NULL;` with `char* str_val;`. Or just use `char* str_val = m.c_str();` – ETech Feb 28 '17 at 05:41
  • @n.m. what should I use ? – 李浩然 Feb 28 '17 at 05:46
  • @ETech Replace char* str_val = NULL with char* str_val; it doesn't work, still segmentfault. – 李浩然 Feb 28 '17 at 05:47
  • 3
    @ETech: No, and no. The first is undefined behavior, the second will not compile. – Benjamin Lindley Feb 28 '17 at 05:47
  • Use std::string, obviously. – n. m. could be an AI Feb 28 '17 at 05:47
  • @DavidSchwartz I modified my question and explain it , does it make sense now ? – 李浩然 Feb 28 '17 at 05:49
  • @n.m. convert a string to string ? ..but that's not what I wan't ... I wanna this function support convert string to char* ... – 李浩然 Feb 28 '17 at 05:51
  • You are trying to use char * pointer without any memory allocation and/or size definition. It seems that you wish to make universal transformer for all types. So, before using char * - allocate memory for m characters or use char[] array. And of course - it shall remove universal effect. – ETech Feb 28 '17 at 05:52
  • 1
    Correct, you don't want to convert a string to a string. You don't need the function supporting types you don't use, so just don't use `char*` and don't worry about the function not supporting it. – n. m. could be an AI Feb 28 '17 at 05:54
  • 2
    Brute forcing this all into one function is possible, but problematic. You could make a specialization that handles `char *` in a much more intelligent manner, but I join the crowd wondering why bother? – user4581301 Feb 28 '17 at 05:55
  • @ETech yeah, I found the error now, thanks !!! – 李浩然 Feb 28 '17 at 05:55
  • @李浩然 Nope, still completely baffled. A `char *` is a C++ pointer type. A pointer can't possibly be stored in a file and be useful since it's only meaningful inside a process. A file can have strings in it. – David Schwartz Feb 28 '17 at 18:05

2 Answers2

3

This segfault is because stringstream does not allocate memory to hold the result of the operation when extracting values into a char* array. It tries to put the values into the memory pointed at by the lhs operand. You must allocate memory yourself.

Here is a simple example:

#include <string>
#include <sstream>
#include <iostream>

template <typename T>
void parse_to_T(const std::string& str, T* result) {
    std::stringstream ss;
    ss << str;
    std::cout << ss.str() << std::endl;
    ss >> *result;
    std::cout << *result << std::endl;
}

int main() {
   char* buffer = new char[256];
   /* Don't do this in real code. If the input is larger than
      the size of the buffer it will end very, very badly.
      always have a way of allocating the correct amount
      of memory.
   */
   int int_val;
   std::string m = "1";
   parse_to_T<int>(m, &int_val);
   char* str_val = NULL;
   parse_to_T<char*>(m, &buffer);
   delete[] buffer;
   return 0;
}

You could include a template specialization for the char* datatype that does the allocation based on the amount of data in the stream (calling stringstream.str().size() should work) but the user would have to free the returned memory.

cbuchart
  • 10,847
  • 9
  • 53
  • 93
JeremiahB
  • 896
  • 8
  • 15
  • 1
    Be careful with fixed-lengths arrays: if input is larger then it will overflow or you may have a security issue. Last is true even if the specification of input states a maximum length, it can always be compromised. – cbuchart Feb 28 '17 at 05:50
  • 2
    No need for `new`. Allocate buffer as a temporary and let the compiler deal with it. – user4581301 Feb 28 '17 at 05:52
  • There's also no need for the both insertion and extraction. `std::istringstream ss(str);` , then the extraction, should be all that is needed. – WhozCraig Feb 28 '17 at 06:00
1

First, your destination variable str_val has no allocated memory, so it is normal you have a segmentation fault.

On the other hand, it would be better if you use std::string instead. If you need the raw pointer const char* then you can use std::string::c_str for so. If you have to modify it then just create a copy.

cbuchart
  • 10,847
  • 9
  • 53
  • 93