EXC_BAD_ACCESS при создании istringstream - PullRequest
3 голосов
/ 19 марта 2012

Этот получил меня.Я пытаюсь написать шаблонную функцию для преобразования строки в различные типы данных.Он должен быть способен компилироваться на двенадцати различных платформах, поэтому использование boost не является удобным вариантом.Я сделал шаг назад, чтобы просто иметь функцию, которая преобразует строку в long.Вот самая базовая версия того, как это выглядит ...

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

Как с шаблонной функцией, так и с этой более конкретной функцией, я получаю плохой доступ к памяти, как только создаю поток istringstream.Если я инициализирую istringstream, не передавая ему переменную str, он все равно падает.Моя трассировка стека выглядит следующим образом ...

(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)

Я попытался добавить string_to_long () в пустой проект C ++, в котором есть только основная функция.Это прекрасно работает в этом сценарии.В приложении, в котором я использую эту функцию, добавление вызовов к ней в определенных точках будет случайным образом работать для одного вызова, а сбой при следующем.Я использовал этот вызов, чтобы проверить его, и он будет успешен каждый раз.

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

У меня нет идей.Похоже, что это связано с компиляцией, компоновкой или проблемой стека.

Возможно, этот файл включает в себя ...

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

... и myfile.h (имя явно не разглашается) включает в себя ...

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

Обновление

Я до сих пор понятия не имею, что является причиной этого.Я потратил несколько днейЯ работаю над этим проектом в Mac OS Lion в Netbeans.Когда я компилирую и запускаю его в Linux и Solaris, используя те же make-файлы, которые генерирует netbeans, это нормально.

Что касается проблемы istringstream, я вытащил istringstream create из вызова функции и сделал его закрытым членомпеременная.Я не в восторге от наличия большего количества переменных-членов, чем это абсолютно необходимо, но в этом случае это обходной путь.Это также немного уменьшит создание объектов.

Проблема сбоя по-прежнему поднимает свою уродливую голову, когда я использую istringstream для преобразования int / long / short, а затем использую тот же поток для преобразования float илидвойной.Вот код, на котором я остановился.Я опубликую обновление, если когда-нибудь выясню, в чем конкретно проблема Mac OS.

Вот код, на котором я остановился на данный момент.Ненавижу, не зная, что это вызывает.

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;
}

1 Ответ

0 голосов
/ 19 марта 2012

Учитывая, что у вас есть обработка потоков в стеке сбоев, вы можете редактировать строку в другом потоке, пока она читается отсюда.Это было бы правдоподобным ответом на то, почему мои тесты не терпят неудачу, ни ваши в меньшем проекте.Ваша строка не является константной, поэтому технически возможно, что std::istringstream мог бы изменить ее, хотя я не вижу причин, по которым это могло бы произойти.

Я бы изменил вашу подпись на string_to_long(const std::string &str) или скопировал бы по значениюи посмотрите, сталкиваетесь ли вы с такими же проблемами.

В качестве примечания, вы всегда должны проверять, установлен ли плохой флаг после преобразования текста из потока.

stream >> n;
if (stream.bad())
  throw std::runtime_error("conversion failed");
...