Динамическое расширение массива char имеет побочные эффекты, когда добавлено более 31 символа (всего) (не считая \ 0) - PullRequest
0 голосов
/ 11 мая 2018

Я адаптировал ответ от C snprintf, чтобы добавить структуру члена char * Некоторые вещи до сих пор неясны.

Какова цель строки * string [used] = 0, которая приводит к ошибкам при нескомментировании и почему возникают побочные эффекты при добавлении более 31 символа?

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

static size_t add_to_string(size_t *used,const char *data,char **string) {

    size_t data_len=strlen(data);

    memcpy(*string+*used,data,data_len);

    *used+=data_len;

    // *string[*used]=0; // uncommenting this causes a segfault

    return *used;
}


int
main(const int argc,const char *argv[])
{
    size_t *used=(size_t*) malloc(sizeof(size_t));

    char *buffer=(char*) malloc(sizeof(char));

    *used=0;

//    char **test=&buffer;

    fprintf(stdout,"There are %d argument(s) to process\n",argc);

    if(1<argc) {

        for(int count=1; count<argc; count++) {

            size_t new_length=add_to_string(used,argv[count],&buffer);
        }

        fprintf(stdout,"%s\n",buffer);

    } else {

        fprintf(stdout,"Nothing to do\n");
    }

    free(used);

    free(buffer);

    return 0;
}

Пример выполнения, показывающий правильное выполнение:

./tmp "one" " " two " " three " " four " " five " " six " " sev
There are 14 argument(s) to process
one two three four five six sev

Пример выполнения, показывающий проблему с добавлением только еще одного символа:

./tmp "one" " " two " " three " " four " " five " " six " " seve
There are 14 argument(s) to process
one two three four five six seveThere are 14 argument(s) to process

Как видите, есть побочные эффекты.

Вальгринд тоже не доволен:

valgrind ./tmp "one" " " two " " three " " four " " five " " six " " seve
==27291== Memcheck, a memory error detector
==27291== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27291== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==27291== Command: ./tmp one \  two \  three \  four \  five \  six \  seve
==27291==
There are 14 argument(s) to process
==27291== Invalid write of size 1
==27291==    at 0x4C33B5B: memmove (vg_replace_strmem.c:1258)
==27291==    by 0x1088B2: add_to_string (tmp.c:9)
==27291==    by 0x10896C: main (tmp.c:36)
==27291==  Address 0x51f4091 is 0 bytes after a block of size 1 alloc'd
==27291==    at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==27291==    by 0x108906: main (tmp.c:24)
==27291==
==27291== Invalid write of size 1
==27291==    at 0x4C33B88: memmove (vg_replace_strmem.c:1258)
==27291==    by 0x1088B2: add_to_string (tmp.c:9)
==27291==    by 0x10896C: main (tmp.c:36)
==27291==  Address 0x51f4097 is 6 bytes after a block of size 1 alloc'd
==27291==    at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==27291==    by 0x108906: main (tmp.c:24)
==27291==
==27291== Invalid read of size 1
==27291==    at 0x4C300D4: strlen (vg_replace_strmem.c:458)
==27291==    by 0x4E884BC: vfprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E8EF23: fprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x10899B: main (tmp.c:39)
==27291==  Address 0x51f4091 is 0 bytes after a block of size 1 alloc'd
==27291==    at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==27291==    by 0x108906: main (tmp.c:24)
==27291==
==27291== Invalid read of size 1
==27291==    at 0x4EB2E5D: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E87CD4: vfprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E8EF23: fprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x10899B: main (tmp.c:39)
==27291==  Address 0x51f40af is 15 bytes after a block of size 16 in arena "client"
==27291==
==27291== Invalid read of size 1
==27291==    at 0x4EB2E74: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E87CD4: vfprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E8EF23: fprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x10899B: main (tmp.c:39)
==27291==  Address 0x51f40ae is 14 bytes after a block of size 16 in arena "client"
==27291==
==27291== Invalid read of size 1
==27291==    at 0x4C345C8: mempcpy (vg_replace_strmem.c:1524)
==27291==    by 0x4EB2D84: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E87CD4: vfprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E8EF23: fprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x10899B: main (tmp.c:39)
==27291==  Address 0x51f40af is 15 bytes after a block of size 16 in arena "client"
==27291==
==27291== Invalid read of size 1
==27291==    at 0x4C345DA: mempcpy (vg_replace_strmem.c:1524)
==27291==    by 0x4EB2D84: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E87CD4: vfprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x4E8EF23: fprintf (in /usr/lib/libc-2.27.so)
==27291==    by 0x10899B: main (tmp.c:39)
==27291==  Address 0x51f40ad is 13 bytes after a block of size 16 in arena "client"
==27291==
one two three four five six seve
==27291==
==27291== HEAP SUMMARY:
==27291==     in use at exit: 0 bytes in 0 blocks
==27291==   total heap usage: 3 allocs, 3 frees, 1,033 bytes allocated
==27291==
==27291== All heap blocks were freed -- no leaks are possible
==27291==
==27291== For counts of detected and suppressed errors, rerun with: -v
==27291== ERROR SUMMARY: 125 errors from 7 contexts (suppressed: 0 from 0)
...