Тонкости работы с функцией strdup

73
01 сентября 2021, 06:30

Создаст ли strdup() '\0' в конце динамического массива?

char buf[128];
buf[0] = 'x';
for(int i = 1; i < 64; i++)
{
    buf[i] = i;
}
char *str = strdup(buf);
Answer 1

Во первых, у Вас опечатка в последней строке:

char *str = strdup(duf); // Надо buf

А во вторых, достаточно сделать man 3 strdup, что бы прочитать:

ОПИСАНИЕ
       Функция  strdup()  возвращает  указатель на новую строку, являющуюся дубликатом строки s.
       Память под новую строку выделятся с помощью malloc(3) и может быть высвобождены с помощью
       free(3).
       Функция strndup() похожа на предыдущую, но копирует не более n байт. Если s длиннее n, то
       копируется только n байт и добавляется конечный байт null ('\0').

Отсюда делаем выводы:

  1. Раз речь идёт о строке (в понимании С), то символ '\0' обязан присутствовать в исходной строке. (Ошибка в Вашей программе)
  2. Если строка слишком длинная, то strndup автоматически вставит этот символ куда нужно.
Answer 2

При i = 0; buf[i] = i; strdup создаст пустую строку. Ноль является признаком конца строки и всегда копируется, как сказано в документации. Аргументом функции является указатель, а слдовательно функция не "знает" размера массива. strndup сделает то же самое, он обрезает строку и добавляет нулевой символ только если не встретит его до n-го элемента.

И откуда такая кривая реализация strdup в ответе? Обычно он реализован вот так

char *strdup(const char *s)
{
  size_t len = strlen (s) + 1;         // длина строки включая нулевой символ
  char *result = (char*) malloc (len);
  if (result == (char*) 0)             // или if (!result)
    return (char*) 0;
  // мы уже знаем длину строки и хотим использовать RVO
  return (char*) memcpy (result, s, len); 
}

либо с использованием встроенных функций. strcpy - потеря времени когда длина строки известна.

Вызов strlen(s), если начиная с адреса s нет нулевого символа в пределах указуемого массива, является источником неопределенного поведения.strdup и strlen являются источниками потенциальных дыр безопасности именно из-за этого, strdup в большей мере т.к. он позволяется информации "утечь" куда-то в результате копирования.

Answer 3

Нет! Функция strdup предназначена для работы со строками потому самостоятельно добавить символ конца строки не может, однако если массив уже имеет '\0' функция скопирует его.

char buf[128];
buf[0] = 'x';
for(int i = 1; i < 64; i++)
{
    buf[i] = i;
}
buf[64] = '\0';// ←←← как-то так
char *str = strdup(buf);

Фактически функция strdup эквивалентна следующему коду:

char *strdup (const char *s) 
{
    char *d = malloc (strlen (s) + 1);   // Space for length plus nul
    if (d == NULL) return NULL;          // No memory
    strcpy (d,s);                        // Copy the characters
    return d;                            // Return the new string
}
READ ALSO
Выброс и перехват исключения [закрыт]

Выброс и перехват исключения [закрыт]

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском

106
Анимация при скролле. Как создавать такие анимации?

Анимация при скролле. Как создавать такие анимации?

Мучает вопрос с анимацией(примеры ниже), никак не могу найти в интернете, может неправильно ищуМне никак не понятно каким образом всё это...

182
Запись и считывание XML файла

Запись и считывание XML файла

Подскажите, у меня есть форма с textbox'ами, как мне записать данные с них в XML файл, и потом считать данные с файла в один отдельный textbox строкой

108