2

I am trying to convert a stringstream into a const char*, but I always get a blank string.

My Code:

#include<string> #include<sstream> #include<stdio.h> const char* test(std::string city, std::string street, int houseNumber, int postCode) { std::stringstream ss; ss << city << " " << street << " " << houseNumber << " " << postCode; const std::string tmp = std::string{ss.str()}; const char* str = tmp.c_str(); return str; } int main(){ printf(test("demo", "Demo", 1, 1234)); } 

Expected Output: demo Demo 1 1234

I tried all the enhancements mentioned in How to convert a std::string to const char* or char*?, but I had no success.

4

3 Answers 3

5

The problem is that the string data your const char* points to has been freed after the return str;. The const char* pointer will stay valid as long as the associated std::string instance is within scope. This is assuming the code you have shown here is located within a function. In that case, the string tmp will go out of scope after the return str;, and its destructor will be called, causing any pointer pointing to its character data to become a dangling pointer.

Return an std::string, and call c_str() on the returned string instead. As mentioned, you can then use the const char* pointer as long as the associated std::string instance is within scope.

Sign up to request clarification or add additional context in comments.

Comments

1

The problem you're encountering is that when this function leaves scope (i.e. when return str; executes), the memory str points to will have been cleaned up. You need to return an object that will maintain ownership over the data.

//std::string_view is >=c++17, use std::string const& for older compilers std::string get_formatted_address( std::string_view city, std::string_view street, std::string_view houseNumber, std::string_view postCode ) { std::stringstream ss; ss << city << " " << street << " " << houseNumber << " " << postCode; return ss.str(); } int main() { auto city = "New York", street = "Rockefeller Lane", houseNumber = "1234", postcode = "56789"; auto formatted_address = get_formatted_address(city, street, houseNumber, postcode); //Here, formatted_address holds ownership over the memory, so calling c_str is safe printf("Address: %s\n", formatted_address.c_str()); } 

Comments

1

You can turn dangling references into non-dangling references by using static thread_local to store a temporary object.

Note that you will only be able to have one active "non dangling" reference at a time:

#include <string> #include <sstream> #include <iostream> const char* to_cstr(std::string && s) { static thread_local std::string sloc; sloc = std::move(s); return sloc.c_str(); } const char* make_address(std::string const& city, std::string const& street, std::string const& houseNumber, std::string const& postCode) { std::stringstream ss; ss << city << " " << street << " " << houseNumber << " " << postCode; return to_cstr(std::move(ss).str()); } int main() { const char* p = make_address("London","Bob Street","42","W1ABC"); std::cout << p << std::endl; } 

expected output:

London Bob Street 42 W1ABC 

http://coliru.stacked-crooked.com/a/228e6c0cb8359222

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.