简体   繁体   English

在C ++中,返回从本地char数组创建的字符串会导致内存泄漏还是未定义的行为?

[英]In C++ does returning a string created from a local char array cause a memory leak or undefined behavior?

I am wondering if this would cause a memory leak or an undefined outcome in C++? 我想知道这是否会导致内存泄漏或C ++中的未定义结果?

string foo()
{
    char tempArray[30];
    strcpy(tempArray, "This is a test");
    return string(tempArray);
}

I know this is a bad thing in C but I haven't found a definite answer for C++. 我知道这在C中是件坏事,但我还没有找到C ++的明确答案。

So everyone is saying no, but I am still confused as to when the memory is deallocated? 所以每个人都说不,但我仍然对内存何时解除分配感到困惑?

Lets say I have this method that calls the above method 让我说我有这个方法调用上面的方法

void bar()
{
    string testString = foo();
}

At what point in the above code does the string object returned from foo() call its destructor? 在上面的代码中,foo()返回的字符串对象在什么时候调用它的析构函数? Is it immediately after getting copied into the object testString? 是否在被复制到对象testString后立即生效?

No, there is no memory leak, and you don't need to do all that, here is equivalent to your code 不,没有内存泄漏,你不需要做所有这些,这相当于你的代码

string foo()
{
 return "This is a test";
}

In this code: 在这段代码中:

char tempArray[30];

tempArray is a variable with automatic storage duration. tempArray是一个具有自动存储持续时间的变量。 When tempArray "falls out of scope" it is automatically destroyed. tempArray “超出范围”时,它会自动销毁。 You copy the contents of this array (somewhat clumsily) in to a std::string and then return that string by value. 您将此数组的内容(有点笨拙)复制到std::string ,然后按值返回该string Then tempArray is destroyed. 然后tempArray被销毁。 It;s important to note here that tempArray is the array . 值得注意的tempArray 是数组 It is not a pointer to the first element of the array (as is commonly mis-perceived), but the array itself. 它不是指向数组的第一个元素的指针(通常是错误的感知),而是数组本身。 Since tempArray is destroyed, the array is destroyed. 由于tempArray被销毁,因此数组被销毁。

There would be a leak if you used a variable with dynamic storage duration, such as with: 如果您使用具有动态存储持续时间的变量,则会出现泄漏,例如:

  char* tempArray = new char[30];
  strcpy(tempArray, "This is a test");
  return string(tempArray);

Note the new[] with no matching delete[] . 注意new[]没有匹配的delete[] Here, tempArray is still a variable with automatic storage duration, but this time it is a pointer, and the thing that it points to has dynamic storage duration. 这里, tempArray 仍然是一个具有自动存储持续时间的变量,但这次它是一个指针,它所指向的东西具有动态存储持续时间。 In other words, tempArray gets destroyed when it falls out of scope, but it's just a pointer. 换句话说, tempArray在超出范围时会被销毁,但它只是一个指针。 The thing that it points to -- the char array itself, is not destroyed because you don't delete[] it. 它指向的东西 - char数组本身,不会被破坏,因为你不delete[]它。

不是特别有效,但没有,没有泄漏。

No, it wouldn't cause any leaks as you never allocate memory on the heap. 不,它不会导致任何泄漏,因为您永远不会在堆上分配内存。 If you used malloc , calloc or new .. and you never free / delete it. 如果您使用malloccallocnew ..并且您永远不会free / delete它。 Then yes, memory leak! 然后是的,内存泄漏!

The array is statically allocated, so it is created on the stack. 该数组是静态分配的,因此它是在堆栈上创建的。 strcpy doesn't return a dynamically allocated object, it fills the existing array, it knows how to do this because of the pointer you passed in - again, not allocated on the heap. strcpy不返回动态分配的对象,它填充现有数组,它知道如何执行此操作,因为您传入的指针 - 再次,未在堆上分配。 A copy of the string object is made when you return the string. 返回字符串时会生成字符串对象的副本。

What happens in your example is that the constructor with the signature 您的示例中发生的是具有签名的构造函数

string ( const char * s );

is called. 叫做。 The constructor allocates new memory for a copy of the string and copies it to that new memory. 构造函数为字符串的副本分配新内存并将其复制到新内存。 The string object is then responsible for freeing its own memory when its destructor is called. 然后,字符串对象负责在调用析构函数时释放自己的内存。

When you make a copy of a string, the copy constructor also allocates memory and makes a copy. 当您复制字符串时, 复制构造函数还会分配内存并进行复制。

You should also take a look at the RAII pattern. 您还应该看看RAII模式。 This is how string 's memory management works. 这就是string的内存管理工作方式。

You can always return local automatic variable from function by value. 您始终可以按值从函数返回本地自动变量。 For any type this should be safe (unless copy constructor is not safe): 对于任何类型,这应该是安全的(除非复制构造函数不安全):

T foo()
{
   return T(...);
}

or: 要么:

T foo()
{
   T t
   return t;
}

Your example matches my first case. 你的例子符合我的第一个案例。

What is not safe is returning pointer/reference to local automatic variable: 什么是不安全的是返回指向本地自动变量的指针/引用:

T& foo()
{
   T t
   return t;
}

T* foo()
{
   T t
   return &t;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM