简体   繁体   English

如何从函数返回字符串文字

[英]How to return a string literal from a function

I am always confused about return a string literal or a string from a function. 关于从函数返回字符串文字或字符串我总是很困惑。 I was told that there might be memory leak because you don't know when the memory will be deleted? 我被告知可能存在内存泄漏,因为您不知道何时会删除内存?

For example, in the code below, how to implement foo() so as to make the output of the code is "Hello World"? 例如,在下面的代码中,如何实现foo()以使代码的输出是“Hello World”?

void foo (       )              // you can add parameters here.
{

}

int main ()
{
    char *c;
    foo (    );
    printf ("%s",c);
    return 0;
}

Also, if the return type of foo() is not void, but you can return char* , what should it be? 另外,如果foo()的返回类型不是void,但是你可以返回char* ,它应该是什么?

I'm assuming we cannot modify main. 我假设我们无法修改main。 To get your program working without a leak, you need something to have static storage: 为了使您的程序在没有泄漏的情况下工作,您需要具有静态存储的东西:

void foo(char*& pC)  // reference
{
    static char theString[] = "thingadongdong";

    pC = theString;
}

But really, this isn't very conventional C++ code. 但实际上,这不是非常传统的C ++代码。 You'd be using std::string and std::cout , so you don't have to worry about memory: 你会使用std::stringstd::cout ,所以你不必担心内存:

std::string foo(void)
{
    return "better thingadongdong";
}

int main(void)
{
    // memory management is done
    std::cout << foo() << std::endl;
}

If you're wondering if something needs to be manually deallocated, it's being done wrong. 如果你想知道某些东西是否需要手动解除分配,那就错了。

Since the old use of char* is being deprecated, can you not simply use a string? 由于旧的char *使用已被弃用,你能不能简单地使用字符串?

const char* func1 () {return "string literal";}

string func2 () {return "another string literal";}

Both of these work fine, with no compiler warnings. 这两种工作都很好,没有编译器警告。

However 然而

char* func3 () {return "yet another string literal";}

will not compile at all. 根本不会编译。 Nor will 也不会

char* func4 () {return &"a ref to a string literal?";}

Stroustrup says in "The C++ Programming Language" (Third Edition): Stroustrup在“The C ++ Programming Language”(第三版)中说:

"A string literal is statically allocated so that it is safe to return one from a function. “字符串文字是静态分配的,因此从函数返回一个是安全的。

const char* error_message (int i)`
{
//...
return "range error";
}

The memory holding range error will not go away after a call of error_messages()." 调用error_messages()后,内存保持范围错误不会消失。“

So every string literal in a program is allocated in its own little piece of memory that lasts for the duration of the program (ie is statically allocated). 因此,程序中的每个字符串文字都分配在自己的小内存中,该内存持续一段时间(即静态分配)。 Putting the const in front of the char* lets the compiler know that you do not intend (and cannot) alter that string literal's little piece of memory which could be dangerous, so they let this assignment slide despite that conversion from string literal to char* is deprecated. 将const放在char *前面让编译器知道你不打算(并且不能)改变那个字符串文字的小内存可能是危险的,所以尽管从字符串文字转换为char *,它们仍然允许这个赋值滑动已弃用。

Returning instead to a string must copy the string literal into an object of type string, memory that the caller is responsible for. 返回到字符串必须将字符串文字复制到string类型的对象中,即调用者负责的内存。

Either way there are no memory leaks: every string literal gets its own piece of memory that is cleaned up on program termination; 无论哪种方式都没有内存泄漏:每个字符串文字都有自己的内存,在程序终止时清理; return to const char* returns a pointer to a literal's piece of memory (knowing you cannot alter it); 返回const char *返回一个指向文字内存的指针(知道你不能改变它); and return to a string makes a copy into a string object existing in the caller's code which is cleaned up by the caller. 并返回一个字符串,将一个副本复制到调用者代码中存在的字符串对象中,该字符串对象由调用者清理。

Though it seems a little ugly notation-wise, I'm guessing they left the const char* to keep the cheap alternative (involving no copies). 虽然看起来有点丑陋的符号,但我猜他们离开了const char *来保留廉价替代品(不涉及副本)。

I am always confused about return a string literal or a string from a function. 关于从函数返回字符串文字或字符串我总是很困惑。

Immutable, literal string 不可变的文字字符串

As I understand it, you are safe to return a string literal directly if the return type is declared const, to declare that the string is not intended to be altered. 据我了解,如果返回类型声明为const,则可以直接返回字符串文字,以声明该字符串不打算更改。 This means you needn't worry about the lifespan of the string / memory leaks. 这意味着您无需担心字符串/内存泄漏的生命周期。

Mutable, non-literal string 可变的,非文字的字符串

However, if you need a string that you can change in-place, you need to consider the lifespan of the string and the size of the memory allocation in which it is stored. 但是,如果需要可以就地更改的字符串,则需要考虑字符串的生命周期以及存储它的内存分配的大小。 This becomes an issue, since you can no longer blithely return the same memory containing string for each invocation of the function, since a previous use could have altered the contents of that memory, and/or may still be in use. 这成为一个问题,因为您不能再为每次调用函数轻松地返回包含字符串的相同内存,因为之前的使用可能已经改变了该内存的内容,和/或可能仍在使用中。 Hence a new piece of memory must be allocated to hold the string returned. 因此,必须分配新的内存来保存返回的字符串。

This is where the potential for a leak occurs, and where the choice needs to be made about where the allocation and de-allocation should occur. 这是发生泄漏的可能性,以及需要在何处进行分配和解除分配的选择。 You could have the function itself allocate the memory and state in the documentation that this happens and stipulate therein that the caller has to free the memory when it is no longer required (preventing a leak). 您可以让函数本身在文档中分配内存和状态,并在其中规定调用者必须在不再需要时释放内存(防止泄漏)。 This means the function can simply return a char *. 这意味着该函数可以简单地返回char *。

The other option is to pass in some memory to the function that was allocated by the caller, and have the function place the string inside that memory. 另一种选择是将一些内存传递给调用者分配的函数,并让函数将字符串放在该内存中。 In this case, the caller both allocates and is responsible for freeing that memory. 在这种情况下,调用者既分配又负责释放该内存。

Finally, I mentioned that the size of the memory and string need to be managed when using a mutable string. 最后,我提到在使用可变字符串时需要管理内存和字符串的大小。 The allocation needs to be both large enough for the string initially set by the function and also for any changed that are made after the function, before the memory is freed. 对于最初由函数设置的字符串,以及在释放内存之前在函数之后进行的任何更改,分配都必须足够大。 Failing to do this correctly can cause a buffer overflow by writing a string to long to fit in the memory initially allocated; 如果不能正确执行此操作可能会导致缓冲区溢出,方法是将字符串写入long以适合最初分配的内存; this is extremely dangerous to the health and security of your program. 这对您的计划的健康和安全极为危险。 It can cause bugs and security holes that are extremely hard to spot (since the source of the error - the overflow - can be far removed from the symptoms seen when the program fails). 它可能导致很难发现的错误和安全漏洞(因为错误的来源 - 溢出 - 可以远离程序失败时看到的症状)。

Something like this: 像这样的东西:

void foo(char ** pChar)
{
    // Make sure the string is shorter
    // than the buffer
    *pChar = new char[256];
    strcpy(*pChar,"Hello World!");
}

Then call it like this: 然后像这样称呼它:

foo(&c);

As mentioned in the comment, be careful the string you are storing is smaller than the buffer or you will get a... stack overflow! 正如评论中所提到的,要小心你存储的字符串小于缓冲区,否则你会得到...堆栈溢出! (Pun intended) (双关语)

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

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