3

这个有我 我正在尝试编写一个模板函数来将字符串转换为不同的数据类型。它必须能够在十二个不同的平台上编译,所以使用 boost 不是一个方便的选择。我已经退后一步,只是拥有一个将字符串转换为长字符串的函数。这是它看起来的非常基本的版本......

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() 添加到一个只有 main 函数的空白 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"

更新

我仍然不知道是什么原因造成的。我花了几天时间修修补补。我正在 Netbeans 的 Mac OS Lion 中处理这个项目。当我使用 netbeans 生成的相同 makefile 在 Linux 和 Solaris 上编译和运行它时,一切正常。

至于 istringstream 问题,我将 istringstream create 从函数调用中提取出来,并将其设为私有成员变量。我并不热衷于拥有比绝对必要更多的成员变量,但在这种情况下,这是一种解决方法。它也会减少对象的创建。

当我使用 istringstream 转换 int/long/short,然后使用相同的流转换 float 或 double 时,崩溃问题仍然出现。这是我确定的代码。如果我弄清楚 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;
}
4

1 回答 1

0

考虑到您在崩溃堆栈中有线程处理,您可能正在另一个线程中编辑字符串,同时从这里读取它。对于为什么我的测试没有失败,你的测试在较小的项目中也没有失败,这将是一个合理的答案。您的字符串不是 const,因此在技术上可以std::istringstream修改它,尽管我看不出有任何理由。

我会将您的签名更改为string_to_long(const std::string &str)或按值复制,看看您是否遇到相同的问题。

作为旁注,您应该始终检查是否在从流进行文本转换后设置了错误标志。

stream >> n;
if (stream.bad())
  throw std::runtime_error("conversion failed");
于 2012-03-19T17:56:09.207 回答