Должны ли мои функции копировать `char *` -arguments? - PullRequest
2 голосов
/ 30 августа 2011

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

void add(char* str)
{
    node *n = malloc(sizeof(node));
    n->value = str;
}

или скорее ...

void add(char* str)
{
    node *n = malloc(sizeof(node));
    char* copy = malloc(strlen(str)+1);
    strcpy(copy, str);
    n->value = copy;
}

Заранее спасибо.

Ответы [ 3 ]

7 голосов
/ 30 августа 2011

это действительно зависит от того, откуда поступают аргументы, и каковы ваши намерения с этими аргументами.

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

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

некоторые конкретные примеры:

  • вы разрабатываете небольшое приложение, которое читает файл CSV, сохраняет значения в связанном списке для сортировки, а затем записывает значения обратно в файл XML: у вас есть контроль надвсе время жизни ваших строк, вам не нужно их копировать.

  • вы пишете библиотеку связанных списков, возможнораспространяются в сети, возможно, используются сотнями людей, работающих во всех областях: вы не знаете, что будет передано в вашу библиотеку, вы не знаете, освободит ли пользователь библиотеки строку перед тем, как манипулировать связаннымисписок, затем вы копируете всю строку.

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

1 голос
/ 30 августа 2011

Что является собственностью str?Это malloc буфер с динамическими данными?Вызывает ли add в вашей программе право владения указателем на связанный список?

Нет правильного ответа, поскольку это зависит от того, как используется str.

0 голосов
/ 30 августа 2011

Я бы предпочел второй вариант, потому что: - - даже если он работает, код не подлежит сопровождению - первый параметр оставляет большой пробел для висячего указателя, если исходная строка str удалена.Невозможно определить, сколько копий указателя str было фактически сделано в программе.- Любые инструменты памяти также будут жаловаться, вызывая раздутый вывод и, следовательно, затрудняют отладку любой реальной проблемы с памятью

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...