EXC_BAD_ACCESS when creating istringstream
It got me. I am trying to write a templated function to convert a string to different data types. It should be able to compile on twelve different platforms, so using boost is not a convenient option. I took a step back to just a function that converts a string to a long one. Here's the simplest version of what she 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 poor memory access as soon as I create the istringstream. If I initialize istringstream without passing the str variable to it, 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 an empty C ++ project that only has a main function. It works great in this scenario. In an application I use this feature, adding calls to it at specific locations will randomly work for one call and fail on the next. I used this call to test it and it will be successful every time after a while.
string num = "1234";
long long_val = string_to_long(num);
I have all the ideas. It seems to have something to do with compilation, linking, or stack issue.
Perhaps this file matters ...
#include <fstream>
#include <sstream>
#include "myfile.h"
... and myfile.h (name not explicitly specified) includes ...
#include <map>
#include <string>
#include "rapidxml/rapidxml.hpp"
Update
I still don't know what is causing this. I spent a few days training. I am working on this project on 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 for the istringstream issue, I pulled istringstream create from the function call and made it a private member variable. I'm not crazy about having more member variables than absolutely necessary, but in this case, this is a workaround. It will also reduce object creation.
The crash problem still causes an ugly head when I use istringstream to convert int / long / short and then use the same stream to convert float or double. Here is the code I ended up with. I will post an update if I find out exactly what the problem is with Mac OS.
Here is the code I ended up with. I hate not knowing what is 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;
}
source to share
Given that you have thread handling on the crash stack, you can edit the line on another thread while it is being read here. This would be a plausible answer to why my tests don't fail, as well as yours on a smaller project. Your string is not a constant, so it is technically possible that it std::istringstream
might modify it, although I see no reason why it would be.
I would change your signature to string_to_long(const std::string &str)
or copy by value and see if you are facing the same problems.
As a side note, you should always check if the error flag is set after converting text from a stream.
stream >> n;
if (stream.bad())
throw std::runtime_error("conversion failed");
source to share