Не удается решить управление памятью (valgrind) в этой программе c - PullRequest
0 голосов
/ 09 июня 2019

Моя проблема заключается в следующем.Я должен создать C-программу, которая объединяет все входные параметры в одном буфере, а затем возвращает этот буфер.Мое решение работает, но есть проблемы с управлением памятью.

Как я могу решить эту проблему?

#define RIALLOCA(buf, newsize) buf = realloc(buf, newsize);

char *mystrcat(char *buf, size_t sz, char *first, ...) {
    va_list l;
    va_start(l, first);

    buf = malloc(strlen(buf) + 1);

    if (sz < strlen(first) + 1) {
        sz += (strlen(first) + 1);
    }

    RIALLOCA(buf, sz + 1 + 16);
    strncat(buf, first, strlen(first));

    char *nextString = va_arg(l, char *);

    while (nextString != NULL) { 
        // sz += strlen(nextString);
        RIALLOCA(buf, strlen(buf) + strlen(nextString) + 1 + 16);
        strncat(buf, nextString, strlen(nextString));
        nextString = va_arg(l, char *);
    }   

    va_end(l);

    return buf;
}   

int main(int argc, char *argv[]) {
    if (argc != 7) {
        printf("troppi pochi argomenti\n");
        return -1; 
    }   
    char *buffer = NULL;
    RIALLOCA(buffer, 16);  // macro che effettua l'allocazione
    buffer[0] = '\0';
    buffer = mystrcat(buffer, 16, argv[1], argv[2], argv[3], argv[4], argv[5],
                      argv[6], NULL);
    printf("%s\n", buffer);
    free(buffer);     
    return 0;
}

Это проблема с Valgrind

enter image description here

Ответы [ 2 ]

0 голосов
/ 09 июня 2019

в функции: mystrcat()

Это утверждение:

buf = malloc(strlen(buf) + 1);

неверно.Поскольку buf уже является указателем на выделенную память И это не изменение указателя buf обратно в функцию main(), а скорее только параметр в стеке.

Чтобы исправить:

в main() (обратите внимание на дополнительный '&' в параметре: buffer)

buffer = mystrcat(&buffer, 16, argv[1], argv[2], argv[3], argv[4], 
argv[5], argv[6], NULL);

в mystrcat() удалить эту строку

buf = malloc(strlen(buf) + 1);

относительно:

if(sz < strlen(first) + 1)
{
    sz += (strlen(first) + 1);
}

, поскольку sz содержит 16, а первый символ в buf равен '\ 0'. Этот оператор if() никогда не будет введен.

Поскольку переданный параметр buf теперьуказатель на указатель, из-за изменения в main() подпись должна быть:

char* mystrcat(char **buf, size_t sz, char *first, ...) 

и все ссылки на buf должны разыменовывать этот параметр для доступа к значению указателя в main()

Существует гораздо больше, но выше перечислены основные проблемы

0 голосов
/ 09 июня 2019

Проблема в том, что - когда вы звоните buf = malloc() внутрь mystrcat() - вы вызываете утечку памяти. Память уже была выделена для buf в вашем main().

.

Изменение

buf = malloc(strlen(buf)+1);

до

buf = realloc(buf, strlen(buf) + 1);

Также ... Я согласен с user3629249: предоставление макросов для стандартных функций библиотеки таким образом, как вы это делаете, кажется излишним - по крайней мере, в этом контексте.

...