使用stringstreams进行strdup会导致valgrind错误

hfh*_*hc2 5 c++ valgrind

我有以下问题:我正在编写一个必须包装C库的C++程序,所以当我与库交互时,我总是必须使用char*而不是std::string所有操作.为了避免char*尽可能多地使用,我使用stringstreams进行格式化,例如:

#include <iostream>
#include <sstream>
#include <string.h>
#include <cstdlib>

using namespace std;

int main(int argc, char** argv)
{
  ostringstream str;

  str << argv[0] << "+" << "hello";

  const char *s = str.str().c_str();

  char *y = strdup(s);

  // this I would give to a library function

  cout << y << endl;

  free(y);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

就输出而言,程序正确输出"./test+hello".但是,valgrind给了我很多类型的错误

==30350== Invalid read of size 1
==30350==    at 0x402B858: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==30350==    by 0x4213475: strdup (in /usr/lib/libc-2.16.so)
==30350==    by 0x41B2604: (below main) (in /usr/lib/libc-2.16.so)
==30350==  Address 0x4341274 is 12 bytes inside a block of size 25 free'd
==30350==    at 0x4029F8C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==30350==    by 0x410387A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.17)
==30350==    by 0x41B2604: (below main) (in /usr/lib/libc-2.16.so)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

jco*_*der 6

 const char *s = str.str().c_str();
Run Code Online (Sandbox Code Playgroud)

str()返回一个字符串对象.您使用c_str获得指向它的某些内部数据的指针,然后在该行的末尾删除字符串对象.但是你仍然有一个指向已删除内部字符串的指针.

你需要这样做 -

std::string s = str.str();
const char* s = s.c_str()
Run Code Online (Sandbox Code Playgroud)

确保不删除字符串.

  • @JonasWielicki是的.临时的生命周期直到完整表达式结束.(我实际上更喜欢这样简洁的东西,但意见各不相同.你不想引入很多不必要的中间变量,但你也不希望表达式过于复杂.截止点所在的位置取决于你问谁.) (3认同)