Как исправить «Использование неинициализированного значения» и как найти место утечки? - PullRequest
0 голосов
/ 20 декабря 2018

Я написал небольшую программу на c, которая получает 3 имени в качестве входных данных и затем сохраняет эти три значения в узле.Три значения (имена) хранятся в массиве JOHNJAKEMATT, каждое имя имеет 4 символа.Получившийся узел выглядит так:

/*
pointer_to_linked_list
       |
       v
    node[2]          node[1]              node[0]
       |                |                    |
       |                |                    |
+------+---+     +------+---+        +-------+------+ 
| MATT | o-----> | JAKE | o--------> |  JOHN | NULL | 
+------+---+     +------+---+        +-------+------+ 
*/

Все хорошо, все работает, как и ожидалось.Каждое имя временно сохраняется в массиве, а затем перемещается в data в узле.Чтобы добиться этого, я выделил память и, если произойдет сбой, я написал функцию, которая должна освободить всю память, если выделение памяти не удается:

void freeNode(struct _Node_ *current_node)
{
struct _Node_ *tmp_node;
while(current_node != NULL) {
    tmp_node = current_node;
    current_node = current_node->next;
    free(tmp_node);
}
return;
}

Также я написал функцию, которая распечатывает мой связанный список:

void printNodes(struct _Node_ *current_node) {
    while(current_node != NULL) {
        printf("%s\n", current_node->data);
        current_node = current_node->next;
    }
}

Результатом в консоли является связанный список с каждым значением:

MATT
JAKE
JOHN

Все работает, тогда я хотел проверить с помощью valgrind (valgrind --leak-check=yes --track-origins=yes ./main), есть лиесть ошибки - и да, есть 2 типа ошибок:

  • неинициализированные значения, я действительно не знаю, где они могут быть ..
  • 3 утечки памяти, есть кто-нибудьПодсказка, где они могут быть?

Полный отчет Valgrind:

==20043== Memcheck, a memory error detector
==20043== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20043== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==20043== Command: ./main
==20043== 
MATT
==20043== Conditional jump or move depends on uninitialised value(s)
==20043==    at 0x1094BC: printNodes (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10928F: main (in /home/osboxes/Dropbox/ESP/main)
==20043==  Uninitialised value was created by a stack allocation
==20043==    at 0x10935C: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043== 
==20043== Use of uninitialised value of size 8
==20043==    at 0x1094A0: printNodes (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10928F: main (in /home/osboxes/Dropbox/ESP/main)
==20043==  Uninitialised value was created by a stack allocation
==20043==    at 0x10935C: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043== 
JAKE
==20043== Use of uninitialised value of size 8
==20043==    at 0x1094AF: printNodes (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10928F: main (in /home/osboxes/Dropbox/ESP/main)
==20043==  Uninitialised value was created by a stack allocation
==20043==    at 0x10935C: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043== 
JOHN
==20043== Conditional jump or move depends on uninitialised value(s)
==20043==    at 0x1094F4: freeNode (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10929B: main (in /home/osboxes/Dropbox/ESP/main)
==20043==  Uninitialised value was created by a stack allocation
==20043==    at 0x10935C: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043== 
==20043== Use of uninitialised value of size 8
==20043==    at 0x1094DB: freeNode (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10929B: main (in /home/osboxes/Dropbox/ESP/main)
==20043==  Uninitialised value was created by a stack allocation
==20043==    at 0x10935C: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043== 
==20043== Conditional jump or move depends on uninitialised value(s)
==20043==    at 0x4838931: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20043==    by 0x1094EE: freeNode (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10929B: main (in /home/osboxes/Dropbox/ESP/main)
==20043==  Uninitialised value was created by a stack allocation
==20043==    at 0x10935C: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043== 
==20043== 
==20043== HEAP SUMMARY:
==20043==     in use at exit: 15 bytes in 3 blocks
==20043==   total heap usage: 7 allocs, 4 frees, 1,087 bytes allocated
==20043== 
==20043== 5 bytes in 1 blocks are definitely lost in loss record 1 of 2
==20043==    at 0x483774F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20043==    by 0x1091D4: copyToNewNode (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10942E: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10932F: readInput (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x109271: main (in /home/osboxes/Dropbox/ESP/main)
==20043== 
==20043== 10 bytes in 2 blocks are definitely lost in loss record 2 of 2
==20043==    at 0x483774F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20043==    by 0x1091D4: copyToNewNode (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x109459: saveToLinkedList (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x10932F: readInput (in /home/osboxes/Dropbox/ESP/main)
==20043==    by 0x109271: main (in /home/osboxes/Dropbox/ESP/main)
==20043== 
==20043== LEAK SUMMARY:
==20043==    definitely lost: 15 bytes in 3 blocks
==20043==    indirectly lost: 0 bytes in 0 blocks
==20043==      possibly lost: 0 bytes in 0 blocks
==20043==    still reachable: 0 bytes in 0 blocks
==20043==         suppressed: 0 bytes in 0 blocks
==20043== 
==20043== For counts of detected and suppressed errors, rerun with: -v
==20043== ERROR SUMMARY: 14 errors from 8 contexts (suppressed: 0 from 0)

Полный код main.c:

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

struct _Node_ 
{
    char *data;
    struct _Node_ *next;
};

struct _Node_ *copyToNewNode(char *pointer_value_linked_list, struct _Node_ *nextnode);
struct _Node_ *readInput(char *pointer_buffer_config, int len_char);
struct _Node_ *saveToLinkedList(char *pointer_tmp_buffer, int str_len, int pos_node);
void printNodes(struct _Node_ *current_node);
void freeNode(struct _Node_ *current_node);

struct _Node_ *copyToNewNode(char *pointer_value_linked_list, struct _Node_ *nextnode) 
{
    struct _Node_ *new_node_pointer;    
    new_node_pointer = malloc(sizeof(struct _Node_));
    if (!new_node_pointer) 
    { 
        freeNode(new_node_pointer);
        return NULL; 
    }

    new_node_pointer->data = malloc(strlen(pointer_value_linked_list) + 1);
    if (!new_node_pointer->data) 
    {
        freeNode(new_node_pointer);
        return NULL;
    }

    strcpy(new_node_pointer->data,pointer_value_linked_list); 
    new_node_pointer->next = nextnode;

    return(new_node_pointer);
}

int main()
{
    char buffer_config[] = "JOHNJAKEMATT";
    struct _Node_ *pointer_to_linked_list;

    pointer_to_linked_list = readInput(buffer_config, strlen(buffer_config));
    if(pointer_to_linked_list == NULL)
    {
        //nodes have already been freed
        return 0;
    }

    printNodes(pointer_to_linked_list);
    freeNode(pointer_to_linked_list);

    return 1;
}

struct _Node_ *readInput(char *pointer_buffer_config, int len_char)
{
    char tmp_buffer_input[5];
    int counter;
    struct _Node_ *pointer_last_node; // points to last successful saved node
    int pos_node = 0;
    int counter_next_node = 0;

    while(counter_next_node != 3)
    {
        for(counter = 0; counter < 4; counter++)
        {
            tmp_buffer_input[counter] = *pointer_buffer_config;
            pointer_buffer_config++; 
        }
        tmp_buffer_input[4] = '\0';

        pointer_last_node = saveToLinkedList(tmp_buffer_input, strlen(tmp_buffer_input), pos_node);

        ++pos_node;
        counter_next_node++;
    }
    return pointer_last_node;
}

struct _Node_ *saveToLinkedList(char *pointer_tmp_buffer, int str_len, int pos_node)
{
char value_linked_list[str_len+1];
int counter = 0;

while(counter != str_len)
{
    value_linked_list[counter] = *(pointer_tmp_buffer+counter);
    counter++;
}
value_linked_list[counter] = '\0';

struct _Node_* node[3];
if(pos_node == 0)  
{
    node[pos_node] = copyToNewNode(value_linked_list, NULL);
}
else
{
    node[pos_node] = copyToNewNode(value_linked_list, node[pos_node-1]);
}  
return node[pos_node];
}

void printNodes(struct _Node_ *current_node) {
    while(current_node != NULL) {
        printf("%s\n", current_node->data);
        current_node = current_node->next;
    }
}

void freeNode(struct _Node_ *current_node)
{
    struct _Node_ *tmp_node;
    while(current_node != NULL) {
        tmp_node = current_node;
        current_node = current_node->next;
        free(tmp_node);
    }
    return;
}

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

1 Ответ

0 голосов
/ 20 декабря 2018

в saveToLinkedList

struct _Node_* node[3];
if(pos_node == 0)  
{
  node[pos_node] = copyToNewNode(value_linked_list, NULL);
}
else
{
  node[pos_node] = copyToNewNode(value_linked_list, node[pos_node-1]);
}  

struct _Node_* node[3] не инициализируется, когда pos_node не равен 0, вы будете использовать запись вектора, не инициализированного => copyToNewNode создаст узел со случайным указателем следующего

struct _Node_* node[3]; должно быть static struct _Node_* node[3];

В freeNode(), который вы пропустили для освобождения полевых данных, должно быть:

void freeNode(struct _Node_ *current_node)
{
   struct _Node_ *tmp_node;
   while(current_node != NULL) {
      tmp_node = current_node;
      current_node = current_node->next;
      if (tmp_node->data != NULL)
         free(tmp_node->data);
      free(tmp_node);
   }
}
...