Как возвратить строковый литерал из функции

Я всегда смущаюсь возвратом строковый литерал или строка от функции. Мне сказали, что могла бы быть утечка памяти, потому что Вы не знаете, когда память будет удалена?

Например, в коде ниже, как реализовать foo() чтобы сделать вывод кода, "Привет Мир"?

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

}

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

Кроме того, если тип возврата foo() не является пустым, но можно возвратиться char*, каково это должно быть?

7
задан Peter Alexander 20 March 2010 в 01:43
поделиться

3 ответа

Полагаю, мы не можем изменить main. Чтобы ваша программа работала без утечек, вам нужно иметь статическое хранилище:

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

    pC = theString;
}

Но на самом деле это не совсем обычный код C ++. Вы бы использовали std :: string и std :: cout , поэтому у вас нет , чтобы беспокоиться о памяти:

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

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

Если вы ' re интересно, нужно ли что-то освободить вручную, это делается неправильно.

10
ответ дан 6 December 2019 в 08:43
поделиться

Меня всегда смущает возврат строкового литерала или строки из функции.

Неизменяемая, литеральная строка

Как я понимаю, вы можете безопасно вернуть строковый литерал напрямую, если тип возвращаемого значения объявлен const, чтобы объявить, что строка не предназначена для изменения. Это означает, что вам не нужно беспокоиться о продолжительности жизни утечек строки / памяти.

Изменяемая, не литеральная строка

Однако, если вам нужна строка, которую вы можете изменить на месте, необходимо учитывать срок службы строки и размер выделенной памяти, в которой она хранится. Это становится проблемой, поскольку вы больше не можете беспечно возвращать одну и ту же память, содержащую строку для каждого вызова функции, поскольку предыдущее использование могло изменить содержимое этой памяти и/или все еще может использоваться. Следовательно, для хранения возвращаемой строки должен быть выделен новый фрагмент памяти.

Именно здесь возникает вероятность утечки, и где необходимо сделать выбор о том, где должно происходить распределение и распределение. Вы можете заставить саму функцию выделить память и состояние в документации, что это происходит, и указать в ней, что вызывающий абонент должен освободить память, когда она больше не требуется (предотвращая утечку). Это означает, что функция может просто вернуть символ *.

Другой вариант заключается в передаче некоторой памяти функции, которая была выделена вызывающей стороной, и помещении функции строки в эту память. В этом случае вызывающий абонент выделяет и отвечает за освобождение этой памяти.

Наконец, я упомянул, что размер памяти и строки необходимо управлять при использовании изменяемой строки. Выделение должно быть достаточно большим как для строки, изначально заданной функцией, так и для любых изменений, которые производятся после функции, до освобождения памяти. Если это сделать правильно, это может привести к переполнению буфера путем записи строки в длину, чтобы поместиться в первоначально выделенной памяти; это крайне опасно для здоровья и безопасности вашей программы. Это может привести к ошибкам и дырам в безопасности, которые чрезвычайно трудно обнаружить (поскольку источник ошибки - переполнение - может быть далек от симптомов, наблюдаемых при сбое программы).

4
ответ дан 6 December 2019 в 08:43
поделиться

Что-то вроде этого:

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

Затем вызовите это так:

foo(&c);

Как упоминалось в комментарии, будьте осторожны, чтобы хранимая строка была меньше буфера, иначе вы получите... переполнение стека! (Pun intended)

2
ответ дан 6 December 2019 в 08:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: