AzerSD
AzerSD

Reputation: 168

strncpy making weird output

I'm trying to make an algorithm for strncpy
I read how it work in the manual and made my algorithm
then I made a test to see if there's any difference between my ft_strncpy and the real strncpy

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

char    *ft_strncpy(char *dest, char *src, unsigned int n)
{
    unsigned int    i;

    i = 0;
    while (i < n && src[i] != '\0')
    {
        dest[i] = src[i];
        i++;
    }
    while (i < n)
    {
        dest[i] = '\0';
        i++;
    }
    return (dest);
}

int main(void)
{
    char src1[] = "123456789q00000";
    char dest1[] = "zzz";
    printf("my output\n");
    printf("src1: %s\n", src1);
    ft_strncpy(dest1, src1, 8);
    printf("dest1: %s\n", dest1);

    printf("\nhow it should be\n");
    char src2[] = "123456789q00000";
    char dest2[] = "zzz";
    printf("src2: %s\n", src2);
    strncpy(dest2, src2, 8);
    printf("dest2: %s\n", dest2);
}

the how it should be section supposed to be the right output of the real strncpy but I'm having weird outputs just like in the code I provided
I get this error

*** buffer overflow detected ***: terminated
signal: aborted (core dumped)

what I understood from the manual is
strncpy copies n first characters from *src to *dest
so a code like

    char src2[] = "123456789q00000";
    char dest2[] = "zzz";
    printf("src2: %s\n", src2);
    strncpy(dest2, src2, 10);
    printf("dest2: %s\n", dest2);

should output : 123456789q as the value of dest I'm I missing smth here?

Upvotes: 2

Views: 197

Answers (2)

chqrlie
chqrlie

Reputation: 144550

strncpy(dest2, src2, 10); has undefined behavior because it will modify 10 bytes starting with dest2[0], yet dest2 is only 4 bytes long.

You have the same problem in ft_strncpy(dest1, src1, 8); for the same reason.

Nothing can be concluded from tests with code that has undefined behavior. The code must be corrected first.

You code for ft_strncpy() seems correct, except for the type unsigned int for the length argument which should be size_t. Using unsigned int is probably a requirement for your school project, but a debatable one, among other counter-productive requirements such as banning for loops and mandating parentheses around the return value.

Here is a modified version:

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

char    *ft_strncpy(char *dest, char *src, unsigned int n)
{
    unsigned int    i;

    i = 0;
    while (i < n && src[i] != '\0')
    {
        dest[i] = src[i];
        i++;
    }
    while (i < n)
    {
        dest[i] = '\0';
        i++;
    }
    return (dest);
}

void dump(const char *prefix, const char *p, size_t size)
{
    size_t i;

    printf("%s: %s  [", prefix, p);
    i = 0;
    while (i < size) {
        printf(" %.2X", (unsigned char)p[i]);
        i++;
    }
    printf(" ]\n");
}
    
int main(void)
{
    char src1[] = "zzz";
    char dest1[] = "123456789q00000";

    printf("my output\n");
    printf("src1: %s\n", src1);
    ft_strncpy(dest1, src1, 8);
    dump("dest1: ", dest1, sizeof dest1);

    printf("\nhow it should be\n");
    char src2[] = "zzz";
    char dest2[] = "123456789q00000";
    printf("src2: %s\n", src2);
    strncpy(dest2, src2, 8);
    dump("dest1: ", dest1, sizeof dest1);

    return 0;
}

Output:

my output
src1: zzz
dest1: : zzz  [ 7A 7A 7A 00 00 00 00 00 39 71 30 30 30 30 30 00 ]

how it should be
src2: zzz
dest1: : zzz  [ 7A 7A 7A 00 00 00 00 00 39 71 30 30 30 30 30 00 ]

Upvotes: 0

AzerSD
AzerSD

Reputation: 168

Arrays in c are not dynamic so
I can't just initialize it with a string then try changing it to a bigger one
that will lead to an undefined behavior

besides there's a corner-case where it might not add the terminating null character so I won't be able to print it with printf because it's not a string anymore, it's an array.

conclusion: Be more cautious when modifying strings.
(answer by the help of @Someprogrammerdude and @n. 1.8e9-where's-my share m.)

Upvotes: 2

Related Questions