Вопрос

После изучения того, что оба strncmp не то, что это кажется и strlcpy Не доступен в моей операционной системе (Linux), я полагал, что могу попытаться написать это сам.

Я нашел цитату из Ульриха Дразма, сопровождающего Libc, который публикул альтернативу strlcpy с использованием mempcpy. Отказ У меня нет mempcpy Либо, но это поведение было легко реплицироваться. В первую очередь, это тестовый камень, у меня есть

#include <stdio.h>
#include <string.h>

#define BSIZE 10

void insp(const char* s, int n)
{
   int i;

   for (i = 0; i < n; i++)
      printf("%c  ", s[i]);

   printf("\n");

   for (i = 0; i < n; i++)
      printf("%02X ", s[i]);

   printf("\n");

   return;
}

int copy_string(char *dest, const char *src, int n)
{
   int r = strlen(memcpy(dest, src, n-1));
   dest[r] = 0;

   return r;
}

int main()
{
   char b[BSIZE];
   memset(b, 0, BSIZE);

   printf("Buffer size is %d", BSIZE);

   insp(b, BSIZE);

   printf("\nFirst copy:\n");
   copy_string(b, "First", BSIZE);
   insp(b, BSIZE);
   printf("b = '%s'\n", b);

   printf("\nSecond copy:\n");
   copy_string(b, "Second", BSIZE);
   insp(b, BSIZE);

   printf("b = '%s'\n", b);

   return 0;
}

И это его результат:

Buffer size is 10                    
00 00 00 00 00 00 00 00 00 00 

First copy:
F  i  r  s  t     b     =    
46 69 72 73 74 00 62 20 3D 00 
b = 'First'

Second copy:
S  e  c  o  n  d          
53 65 63 6F 6E 64 00 00 01 00 
b = 'Second'

Вы можете видеть во внутреннем представлении (линии insp() создан) что есть немного шума, как printf() Формат строки в проверке после первой копии и иностранного 0x01 во второй копии.

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

Но почему есть содержимое иностранного массива (из строки формата) внутри моего пункта назначения? Это так, как будто место назначения фактически изменена для соответствия новой длине.

Это было полезно?

Решение

Конец строки отмечен a 0 памятью после того, как это может быть что-нибудь, если только ваша ОС не заготовит его, то это просто что-то, что не осталось там.

Примечание. В этом случае «проблема» не в файле copy_String, вы точно копируете 10chars - но память после «первого» в вашем основном коде является просто случайным.

Другие советы

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

Вы можете легко увидеть, что вы копируете исходную строку с его нулевым терминатором. Но так как вы memcopying 10 байтов, и оба строки "сначала" и "второе", короче 10 байтов, вы также копируете дополнительные байты мимо них.

Использование memcpy(dest, src, n-1) вызывает неопределенное поведение, если dest а также src не оба по крайней мере n-1 в длину.

Например, First\0 в длину шесть символов, но вы читаете n-1 (9) символы из него; Содержимое памяти промирает конец строкового литерала неопределен, как и поведение вашей программы при прочтении этой памяти.

Дополнительные «вещи» там, потому что вы пропустили размер буфера на memcpy. Отказ Он собирается скопировать, что многие персонажи, даже когда источник короче.

Я бы сделал вещи немного по-другому:

void copy_string(char *dest, char const *src, size_t n) { 
    *dest = '\0';
    strncat(dest, src, n);
}

В отличие от strncpy, strncat определяется для работы, как большинство людей разумно ожидают.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top