Как эта реализация C-функции memccpy () не вызывает ошибки на следующем входе? - PullRequest
0 голосов
/ 13 февраля 2019

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

Я попытался посмотреть, что произойдет, если длина принятого файла превысит длину входного массива.Конечно, я ожидал сегфо, но, к моему удивлению, этого не произошло.Вот реализация функции:

void    *ft_memccpy(void *str_dest, const void *str_src, int c, 
size_t n)
{
    unsigned int    i;
    char            *dest;
    char            *src;
    char            *ptr;

    dest = (char *)str_dest;
    src = (char *)str_src;
    i = 0;
    ptr = 0;
    while (i < n && ptr == 0)
    {
        dest[i] = src[i];
        if (src[i] == ((char)c))
            ptr = dest + i + 1;
        i++;
    }
    return (ptr);
}

И код, использованный для его проверки:

int main()
{
    int num1[5] = {1, 2, 3, 4, 5};
    int num2[5] = {0, 0, 0, 0, 0};

    int (*num1p)[5] = &num1;
    int (*num2p)[5] = &num2;

    for (int i = 0; i < 5; i++)
    {
        printf("value before copy = %d\n", num2[i]);
    }
    //THE INPUT
    ft_memccpy(num2p, num1p, 9, (sizeof(int)*8));
    for (int i = 0; i < 5; i++)
    {
        printf("value after copy = %d\n", num2[i]);
    }

    return 0;
}

Я ожидал, что произойдет segfault, поскольку переданные параметры были 9 и 32байт для размера (8 * sizeof (int)).Я подумал, что, поскольку сам размер массива составляет всего 20 байтов, он будет работать с ошибкой, как только пройдет 20 байтов в строке dst [i] = src [i], но это не так.Действительно, когда я передаю эти же параметры в стандартную версию C, это также не вызывает ошибки.Что может быть причиной этого?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

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

Кроме того, как могут изменяться неопределенные проявления поведения, внося, казалось бы, несвязанные изменения, такие как дополнительные printf для отладки или добавлениянеиспользуемая локальная переменная.Это также может измениться с помощью других настроек оптимизации или другого компилятора.Например, когда я запустил ваш код, он обнаружил разрушение стека и произошел сбой с помощью SIGABORT.

То, что может произойти сбой , не означает, что будет .

0 голосов
/ 13 февраля 2019

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

Точкакод ошибочен, но segfaults обычно не происходит, если вы не пытаетесь записать в указатель NULL, значительно за пределами выделенной памяти, или вы просто «повезло» и случайно перезаписали буфер в концевыделенная страница (и, следовательно, запись в нераспределенную страницу).

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