3

This one's got me. I'm trying to write a templated function for converting a string into different data types. It has to be able to compile on twelve different platforms, so using boost isn't a convenient option. I've taken a step back to just having a function that converts a string to a long. Here is the very basic version of what it looks like...

long string_to_long(string &str) {
    istringstream stream(str);
    long n;
    stream >> n;
    return n;
}

With both the templated function, and this more specific function I get a bad memory access as soon as I create the istringstream. If I initialize the istringstream without passing it the str variable, it still crashes. My stack trace looks like this...

(gdb) thread apply all bt

Thread 1 (core thread 0):
#0  0x00007fff89ba35b6 in pthread_threadid_np ()
#1  0x00007fff89ba10b9 in pthread_mutex_lock ()
#2  0x00007fff8ab1baf5 in __gnu_cxx::__mutex::lock ()
#3  0x00007fff8ab22903 in std::locale::locale ()
#4  0x00007fff8ab2c582 in std::basic_ios<char, std::char_traits<char> >::basic_ios ()
#5  0x00007fff8ab44d2e in std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >::basic_istringstream ()
#6  0x000000010e0b53e3 in my_file::string_to_long (this=0x7fff6dca0380, str=@0x7fff6dc9ff20) at my_file.cpp:46
#7  0x000000010e0b72e8 in my_file::add_prop (this=0x7fff6dca0380, props=0x7f9013c01510, prop_node=0x7fff6dca16c0) at my_file.cpp:392
#8  0x000000010e0b8864 in my_file::run_test_section (this=0x7fff6dca0380, tests_node=0x7fff6dca0428, section_name=@0x7fff6dcb0500, sibling_name=@0x7fff6dcb04f0) at my_file.cpp:135
#9  0x000000010e0b2b3b in main (argc=3, argv=0x7fff6dcb0828) at main.cpp:39
(gdb)

I tried adding string_to_long() to a blank C++ project that only has a main function. It works fine in that scenario. In the app I'm using this function in, adding calls to it in certain spots will randomly work for one call, and crash on the next. I've been using this call to test it, and it will succeed every once in awhile.

string num = "1234";
long long_val = string_to_long(num);

I'm all out of ideas. It seems like it's something related to compiling, linking, or a stack issue.

Possibly of importance, this file is including...

#include <fstream>
#include <sstream>
#include "myfile.h"

... and myfile.h (name obviously withheld) includes...

#include <map>
#include <string>
#include "rapidxml/rapidxml.hpp"

Update

I still have no clue about what is causing this. I've spent days tinkering. I'm working on this project in Mac OS Lion in Netbeans. When I compile and run it on Linux and Solaris using the same makefiles that netbeans generates, it's fine.

As far as the istringstream issue, I pulled the istringstream create out of the function call and made it a private member variable. I'm not crazy about having more member variables than are absolutely necessary, but in this case it's a workaround. It'll also reduce object creation a bit too.

The crash problem still rears its ugly head when I use the istringstream to convert an int/long/short, and then use that same stream to convert a float or double. Here's the code I settled on. I'll post an update if I ever figure out what the Mac OS specific issue was.

Here's the code I settled on for now. I hate not knowing what's causing this.

template<class T>T string_to(const string &str) 
{
    stream.str(str);
    T t;
    stream >> t;
    if (stream.fail()) {
        runtime_error("Conversion failed");
    }
    stream.clear();
    return t;
}
Phil Viso
  • 643
  • 7
  • 11
  • Is that now the only code? Unexplained things like this are quite often due to some unrelated code having corrupted some important mrmory somewhere... – jcoder Mar 20 '12 at 16:54

1 Answers1

0

Considering you have thread handling in the crash stack you may be editing the string in another thread while it is being read from here. That would be a plausible answer for why my tests do not fail, nor yours in a smaller project. Your string is not const, so it is technically possible that std::istringstream could be modifying it, though I don't see any reason it would.

I would change your signature to string_to_long(const std::string &str) or copy by value and see if you encounter the same issues.

As a side note, you should always check to see if the bad flag is set after text conversion from a stream.

stream >> n;
if (stream.bad())
  throw std::runtime_error("conversion failed");
Tom Kerr
  • 10,444
  • 2
  • 30
  • 46
  • I'm not sure why there is thread handling in my stack trace. This isn't a multi-threaded application. It uses a few std libraries (map, string, vector) and rapidxml. Notice in my gdb output, I did thread apply all. That's the only thread I'm using. Like I mentioned in my post, it still crashes if I initialize the istringstream without a string, so the value I'm passing in doesn't seem to matter. – Phil Viso Mar 19 '12 at 18:13
  • @PhilViso That is strange to say the least. I would start commenting out parts of your application and see if there is some interaction that you can identify. – Tom Kerr Mar 19 '12 at 18:29