Выход изменяется в зависимости от позиции вызова функции в программе - PullRequest
0 голосов
/ 01 мая 2020

Я сейчас учусь C. Одна из вещей, которую я хочу сделать, чтобы выздороветь, это mimi c функция "strcat" из заголовка. Чтобы сделать более точную копию, я сравниваю вывод своей собственной функции с выводом исходной. Они используют одинаковые, но разные массивы символов. Однако вывод моей собственной функции изменяется, если она вызывается после исходной. Вот два варианта кода:

В первом вывод оригинала "1234567890123456" , как и ожидалось, и вывод моего * "123456789123456" . Я обнаружил после нескольких десятков различных проверок: символ '0' исчезает из src [0] , как только он передается функции в качестве параметра:

int main()
{

    char dest[10] = "123456789";
    char src[70] = "0123456";
    printf ("Concatenate |%s| and |%s|\n", dest, src); 


    char dest1[10] = "123456789";
    char src1[70] = "0123456";
    printf ("Normal people do: %s\n", strcat(dest1, src1));    
    printf ("Your filthy code: %s\n",  ft_strcat(dest, src));


    return 0;
}

Однако, если я просто переместлю printf своей функции следующим образом:

int main()
{

    char dest[10] = "123456789";
    char src[70] = "0123456";
    printf ("Concatenate |%s| and |%s|\n", dest, src);     
    printf ("Your filthy code: %s\n",  ft_strcat(dest, src));


    char dest1[10] = "123456789";
    char src1[70] = "0123456";
    printf ("Normal people do: %s\n", strcat(dest1, src1));    
    return 0;
}

обе функции вернут "1234567890123456" в качестве вывода.

Вопрос : как это возможно? Мне любопытно, потому что эти функции адресованы двум различным наборам массивов и поэтому не должны влиять друг на друга. По какой-то причине поведение моей функции меняется в зависимости от того, когда она вызывается в теле int main () .

Пожалуйста, обратите внимание , что я намеренно сделал массив dest [] размером 10 символов, так как я хочу имитировать c поведение оригинального strcat в неожиданных ситуациях. Хотя это, вероятно, является ядром проблемы, и, если я изменю его, код работает хорошо в обоих вышеупомянутых случаях. Как я уже сказал, меня интересует природа проблемы, а не способы ее решения.

Я не уверен, что текст моей функции имеет отношение к этой проблеме, но вот она, просто в случае:

char *ft_strcat(char *dest, char *src)
{
    int dest_end;
    int src_count;

    dest_end = 0;
    src_count = 0;
    while (dest[dest_end])
        dest_end++;
    while (src[src_count])
    {
        dest[dest_end] = src[src_count];        
        src_count++;
        dest_end++;
    }
    dest[dest_end + 1] = '\0';
    return dest;
}

Спасибо за любые ответы.

Ответы [ 2 ]

0 голосов
/ 01 мая 2020
char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Your filthy code: %s\n",  ft_strcat(dest, src));

char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1)); 

В обоих случаях, используя собственную функцию ft_strcat(dest, src)) или strcat(), вы вызываете неопределенное поведение , поскольку массивы char, на которые указывает пункт назначения, не способны удерживать инициализированная строка плюс добавленные строки, на которые указывает источник. При записи за пределы массива поведение программы не определено.


Решение:

Массивы dest и dest1 должны иметь как минимум 18 Всего элементов, 10 для удержания "0123456789", 7 для добавления "0123456" + 1 элемента для завершающего нулевого символа \0:

char dest[18] = "123456789";
char dest1[18] = "123456789";

char src[70] = "0123456";
char src1[70] = "0123456";

printf ("Your filthy code: %s\n",  ft_strcat(dest, src));
printf ("Normal people do: %s\n", strcat(dest1, src1));

Сторона примечания:

  1. Массив scr1 является избыточным, поскольку он служит только для предоставления добавляемой строки и в точности совпадает со своим содержимым со строкой в ​​src. Вы также можете использовать src для второго процесса добавления:
printf ("Normal people do: %s\n", strcat(dest1, src));
src и src1 содержат каждый элемент 70, что не нужно. Они оба должны иметь только 8 элементов, а не 70:
src[8] = "0123456";
src1[8] = "0123456";

Более удобный подход - опустить количество элементов и позволить компилятору автоматически определять количество требуемых элементов. Это также гарантирует, что вы не забудете нулевой символ при подсчете:

src[] = "0123456";
src1[] = "0123456";
Поскольку указатель src и его остроконечный объект не будут изменены внутри ft_strcat(), объявите src как char const * const src.

dest также можно сделать const, но без указания указателя на const char: char * const dest.

Вы также можете адаптировать тип возвращаемого значения ft_strcat() относительно указателя dest.

Результат :

char * const ft_strcat(char * const dest, char const * const src)
0 голосов
/ 01 мая 2020

Это связано с перекрытием памяти .... потому что вы объявляете размер dest1[10] и dest[10] вместо того, чтобы объявлять эти два массива с большей длиной, как эта

char dest1[100];
char dest[100];

ваша проблема будет решена.

...