返回std :: string时指针无效(所以说libc)

时间:2015-01-18 08:22:27

标签: c++ linux stdstring g++4.8

我在mmapped-file-consume类中有一个成员函数,如下所示:

std::string Data::GetASCIIZ(OFFSET* offsetp) const
{
  char* str = (char*)_buffer + *offsetp;  // _buffer points to mmap'd file
  *offsetp += strlen(str) + 1;
  return std::string(str);
}

('OFFSET'的类型是unsigned long long)

它的存在理由是(a)返回一个以空值终止的C字符串的std ::字符串,该字符串被假定存在于偏移*offsetp,之后(b)提升{{{ 1}}超过所述C字符串的结尾。

我在很多情况下都会调用此函数,没有问题。但是,我最近添加了一个新的调用,它总是以一种特殊的方式使用SIGABRT:

*offsetp

上面的消息之后是一个回溯(在libc.so.6中的一些代码中达到顶点),以及一个内存映射......在调试这个问题时,这两个对我来说都是显而易见的。

通过GDB调试,我了解到SIGABRT实际上并不是在我上面引用的*** glibc detected *** /home/ryan/src/coolapp/out/coolapp: free(): invalid pointer: 0xb7eb165c *** 方法中发生的,而是在赋值右侧调用它的代码中。 (所以,我在调用std :: string的拷贝构造函数时假定:)

[编辑:更新后与@WhozCraig的预期答案相吻合]

Data::GetASCIIZ

在这种特殊情况下,偏移量struct stuff { char version; std::string sigstring; // ... }; stuff* mystuff = (stuff*)malloc(sizeof(stuff)); // ... mystuff->sigstring = _data->GetASCIIZ(offsetp); // SIGABRT HAPPENS AT THIS SCOPE 处的C字符串恰好是一个空字符串,但我已经通过临时修改*offsetp以指向其他字符串来验证这不是后果在GDB内。

我的方法标记为*offsetp,因为它不会修改const对象的任何内部状态。我正在返回一个存在于堆栈中的对象,但我没有通过引用这样做,并且我希望复制构造函数(在调用代码中)在该堆栈项被破坏之前做正确的事。

我尝试重写Data方法以使用显式本地方法,但这没有帮助。

我错过了什么吗?

如果它有用,这里是解析在此SIGABRT发生时的分配调用。 ('==>'就在错误点。)

GetASCIIZ

1 个答案:

答案 0 :(得分:-1)

您的样本如下。

std::string Data::GetASCIIZ(OFFSET* offsetp) const
{
  char* str = (char*)_buffer + *offsetp;  // _buffer points to mmap'd file
  *offsetp += strlen(str) + 1;
  return std::string(str);
}

return语句不应该返回 new STL字符串吗?

std::string Data::GetASCIIZ(OFFSET* offsetp) const
{
  char* str = (char*)_buffer + *offsetp;  // _buffer points to mmap'd file
  *offsetp += strlen(str) + 1;
  return new std::string(str);
}