Я адаптировал ответ от 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)