Реализация оригинальной функции strlcpy на Libc

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

size_t  ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
    unsigned int    i;
    unsigned int    dst_len;

    i = 0;
    dst_len = strlen(dst);
    if (dstsize > 0)
    {
        while (src[i] != '\0' && i < dstsize - 1)
        {
            dst[i] = src[i];
            i++;
        }
        dst[i] = '\0';
    }
    return (strlen(src));
}

int    main(void)
{
    char dst[100] = "HelloWorld!";
    char dst2[100] = "HelloWorld!";

    const char src[11] = "teststring";
    int dstsize = -1;
    printf("mine : %zu\n", ft_strlcpy(dst, src, dstsize));
    printf("%s\n", dst);
    printf("string.h : %zu\n", strlcpy(dst2, src, dstsize));
    printf("%s\n", dst2);


    return (0);
}

Этот код является моим кодом реализации strlcpy самостоятельно.

но у меня есть один сомнительный вопрос.

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

но оригинальная ошибка трассировки strlcpy print (возможно, SIGILL в Linux. Я использую OS X)

Реализация оригинальной функции strlcpy на Libc

Я искал большую часть оригинальной библиотеки bsd c на github, но все они работают так же, как мой код. Я хочу знать разницу. как исходная ошибка печати strlcpy, когда dstsize является отрицательным числом?

Суть этого вопроса заключается в том, «как распечатать ошибку ловушки трассировки, когда dstsize является отрицательным числом, как исходная функция? (Я знаю, что он будет преобразован в максимальное число size_t.)»

size_t — беззнаковый тип, поэтому он не может быть отрицательным. Но в любом случае, какое сообщение об ошибке вы ожидаете?
Jabberwocky 21.03.2022 08:35
dstsize не может быть отрицательным числом, так как это тип size_t, который является типом без знака. Когда аргумент равен -1, он будет преобразован в беззнаковое значение, которое является максимальным значением size_t.
Paul Hankin 21.03.2022 08:35

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

jyoung 21.03.2022 08:37

Примечание: const char src[10] = "teststring";, вероятно, не то, что вам нужно. Здесь src не завершается нулем, потому что нет места для завершающего нуля. Вы, вероятно, хотите char src[11] = ... или лучше char src[] = .... В последнем случае компилятор позаботится о том, чтобы зарезервировать нужное количество памяти для вашей строки.

Jabberwocky 21.03.2022 08:39

@Jabberwocky извини за это. но суть этого вопроса не в этом..

jyoung 21.03.2022 08:42

@jyoung Я знаю, поэтому это «примечание». Это бонус, бери или уходи.

Jabberwocky 21.03.2022 08:42

@Jabberwocky src проблема не в том, чтобы заканчиваться нулем. Первое, что делает strlcpy, это strlen(src) видит github.com/apple/darwin-xnu/blob/main/osfmk/arm/strlcpy.c . Я думаю, что это случай того, что UB ведет себя по-разному в двух случаях и не имеет ничего общего с dstsize.

Paul Hankin 21.03.2022 08:47

Если вы замените объявление src на const char *src = "teststring";, я думаю, ловушки нет.

Paul Hankin 21.03.2022 08:48

@PaulHankin, если src выдает ошибку, первый вывод «mine: 10» не должен быть напечатан.

jyoung 21.03.2022 08:54

@jyoung src не завершается нулем, поэтому все ваши тесты бессмысленны.

Jabberwocky 21.03.2022 09:04

@jyoung исходная функция strlcpy также не работает с отрицательным размером, поскольку size_t не имеет знака.

Jabberwocky 21.03.2022 09:06

@Jabberwocky, пожалуйста, еще раз посмотрите на мой вопрос. Я отредактировал код. но происходит та же ошибка

jyoung 21.03.2022 09:09

@jyoung, а какой результат вы ожидаете?

Jabberwocky 21.03.2022 09:22

@Jabberwocky нужен сигнал ловушки трассировки, как в оригинальной функции.

jyoung 21.03.2022 09:24

@jyoung исходная функция strlcpy не задокументирована для этого. Если src завершается нулем (как в отредактированной версии вашего кода), ваш код работает нормально без каких-либо сообщений об ошибках. Проверьте это: godbolt.org/z/fjPbE15zj. Кстати: не объявляйте свои строки так: const char src[11] = "teststring";, это плохая практика и чревато ошибками. Сделайте это: const char src[] = "teststring";

Jabberwocky 21.03.2022 10:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
15
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет смысла вычислять длину строки в dst для strlcpy: dst_len = strlen(dst); бесполезно и контрпродуктивно.

Вот модифицированная версия:

size_t  ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
    size_t    i;

    i = 0;
    while (i + 1 < dstsize && src[i] != '\0') {
        dst[i] = src[i];
        i++;
    }
    if (i < dstsize) {
        dst[i] = '\0';
    }
    while (src[i] != '\0') {
        i++;
    }
    return i;
}

Что касается вашего вопроса:

how to print trace trap error when dstsize is a negative number?(I know it will be converted to size_t max number.)

Если размер адресата, переданный вызывающей стороной, является отрицательным числом, то есть результатом некоторого вычисления, которое производит или могло бы произвести отрицательное число с использованием арифметики со знаком, оно преобразуется в size_t по модулю SIZE_MAX + 1, следовательно, значение огромно.

Вы можете обнаружить это путем сравнения:

 if (dstsize > SIZE_MAX >> 1) {
     fprintf(stderr, "ft_strlcpy: huge dstsize indicates a negative value was passed: %zd\n", dstsize);
     abort();
 }

Дело не в этом... дело в том, "как распечатать ошибку ловушки трассировки, когда dstsize является отрицательным числом? (Я знаю, что он будет преобразован в максимальное число size_t.)"

jyoung 21.03.2022 08:40

@jyoung, как упоминалось несколько раз, dstsize — это беззнаковое значение. Оно не может быть отрицательным.

Jabberwocky 21.03.2022 08:41

Ага. после -1 конвертировать в максимальное число size_t, это то же самое, что и максимальное число size_t в dstsize. когда это происходит, как распечатать ошибку ловушки трассировки, как исходную функцию?

jyoung 21.03.2022 08:47

спасибо за дополнительный ответ. так это единственный способ напечатать ошибку с функцией прерывания? Я думаю, что «SIGABORT» — это не тот же знак «SIGTRAP» (OS X) или «SIGILL» (LINUX).

jyoung 21.03.2022 09:05

@jyoung: вы можете отправить сигнал с помощью системного вызова raise: #include <signal.h> [...] raise(SIGTRAP);

chqrlie 21.03.2022 11:52

@chqrlie Спасибо за ваш ответ. Это было полезно!

jyoung 22.03.2022 06:45

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