【问题标题】:invalid read size of 1 valgrind1 valgrind 的无效读取大小
【发布时间】:2012-07-21 12:38:21
【问题描述】:

我一直在抓挠头发,但似乎找不到以下代码有什么问题。这是它生成的 valgrind 输出的小 sn-p

在 0x4c22d82 处读取大小为 1 的无效:strlen (mc_replace_strmem.c:242) 由 0x5E65CA: Application::readConfigurationFile() (char_traits.h:262) 由 0x5694BD: 主地址 0xafc9660 是一个大小块内的 24 个字节 39 在 0x4C20E0D 释放:操作员删除(无效 *) (vg_replace_malloc.c:342) 由 0x635618: Configurator::getParameterValue(char const*, char**) by 0x5E65B2: Application:readConfigurationFile() (Application.cpp:77) by 0x5694BD: 主要的

bool Configurator::getParameterValue(const char *p_pParameterName, char** p_pParameterValue)
{
    bool blReturnValue = false;

    QDomElement element;
    QDomNode node;
    QDomNodeList list;

    list = doc.elementsByTagName(p_pParameterName);
    if (!list.isEmpty())  
    {
        node = list.item(0);
        element = node.toElement();
        QString qs = element.text().toUtf8();
        *p_pParameterValue = (char *)(qs.toStdString().c_str());
        blReturnValue = true;
    }
    else
    {
        char sMessage[200];
        sprintf(sMessage, "<Configurator::getParameterValue> Error! Parameter %s could not be found\n", p_pParameterName);
        m_outputFunction(sMessage);
    }

    return blReturnValue;
}

bool Configurator::parseFile()
{
    bool blReturnValue = false;

    QString errorStr;
    int errorLine;
    int errorColumn;

    if (!doc.setContent((QIODevice*)(&file), true, &errorStr, &errorLine, &errorColumn))
    {
        char aTemp[512];
        sprintf(aTemp, "<Configurator::parseFile> error! can not read the file row: %d, column: %d:\n",errorLine, errorColumn);
        m_outputFunction(aTemp);
    }
    else
    {
        closeFile();
        blReturnValue = true;
    }

    return blReturnValue;
}

bool Application::readConfigurationFile()
{
    bool blReturnValue = false;

    m_outputFunction("<Application::readConfigurationFile> Reading configuration..\n");

    if(m_configurator.parseFile())
    {
        blReturnValue = true;

        m_configurator.writeParameters();

        char *pTemp = 0;


        if(!m_configurator.getParameterValue("center_no", m_bCenterNo)) 
            m_bCenterNo = 1;
        if(m_configurator.getParameterValue("highway_header", &pTemp))
            m_strHighwayHeader.assign(pTemp);
        else
            m_strHighwayHeader.assign("... HIGHWAY"); // Default value
    }
    return blReturnValue;
}

谁能告诉我为什么我看到无效的读取,我什至没有在这段代码 sn-p 中使用 malloc/calloc。

【问题讨论】:

    标签: c++ valgrind


    【解决方案1】:
    *p_pParameterValue = (char *)(qs.toStdString().c_str());
    

    你为什么这样做? QString 是局部变量,toStdString 返回新的std::string

    std::string QString::toStdString () const
    

    因此,返回的 std::string 将被删除。 c_str() 返回指向 const char* 的指针。引自 n3337 草案:

    const charT* c_str() const noexcept;
    const charT* data() const noexcept; 
    

    1 返回:一个指针 p 使得 p + i == &amp;operator[](i)[0,size()] 中的每个我。 2 复杂性:恒定的时间。 3 要求: 程序不得更改存储在字符中的任何值 数组。

    if(m_configurator.getParameterValue("highway_header", &pTemp))
                    m_strHighwayHeader.assign(pTemp);
    

    错了。由于 pTemp 中的值被删除,所以当临时对象 qs.toStdString() 被删除时。

    【讨论】:

      【解决方案2】:

      您实际上是在返回一个指向局部变量的指针。在getParameterValue 中,变量qs 是块内的局部变量,您将该字符串指针分配给p_pParameterValue。当getParameterValue 之前由qs 占用的堆栈空间现在被回收并且指针pTemp 现在指向未使用的内存。这是未定义的行为,可能会导致很多不好的事情发生。

      【讨论】:

      • 感谢您的回复,所以我应该使用 strncpy 而不是这样做,对吗?
      • @erinc 不,那么您必须分配和释放内存。我的建议是您要么使用对QStringstd::string 的引用。
      【解决方案3】:

      qs.toStdString() 返回的临时字符串对象为字符串分配内存,当临时对象被销毁时(在评估完整表达式之后),该内存将被释放。如果您使用优化进行编译,std::string d'tor 很可能已内联到您的函数中,因此它不会显示在您的调用堆栈中。

      当你想在函数完成后继续使用字符串数据时,你需要让它持久化。 (在我看来)最明智的方法是返回一个std::string 对象而不是char *,因此最后一个参数可以是std::string **(由new std::string(qs.toStdString()) 填充)或std::string &amp;,即分配给。

      如果你有 Boost 库,你也可以使用 boost::optional&lt;std::string&gt; 作为返回类型,它提供了一个“带有有效标志的字符串”数据类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-17
        • 2020-09-30
        • 2014-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多