2014-12-21 4 views
0

Я написал тривиальное приложение на C++, которое просто считывает строки из stdin и сохраняет их в куче в связанном списке. Не знаю, почему Valgrind злоупотребляет этим фрагментом кода ... Где это «недопустимое чтение»? Неправильно ли я освобождаю память, выделенную для связанного списка?Повреждение памяти в C++ связанном списке

1_9.cpp

#include <iostream> 
#include <string> 

struct Node { 
    std::string str; 
    Node* next; 
}; 

int main() 
{ 
    std::string line; 
    Node* head = NULL; 
    Node* _curr = NULL; 
    Node* _new = NULL; 

    std::cout << "Ready for reading from stdin..." << std::endl; 
    while(std::getline(std::cin, line)) 
    { 
     if (!head) 
     { 
      head = new Node; 
      head->str = line; 
      _curr = head; 
     } 
     else 
     { 
      _new = new Node; 
      _new->str = line; 
      _curr->next = _new; 
      _curr = _new; 
     } 
    } 

    std::cout << "Reading finished. Here are the results:" << std::endl; 
    for (Node* _node = head; _node != NULL; _node = _node->next) 
    { 
     std::cout << "\t" << _node->str << std::endl; 
    } 

    std::cout << "Cleaning the memory..." << std::endl; 
    for (Node* _node = head; _node != NULL; _node = _node->next) 
    { 
     std::cout << "\t Deleting:" << _node->str << std::endl; 
     delete _node; 
    } 

    std::cout << "Bye!" << std::endl; 
    return 0; 
} 

1_9.test:

asdfhjkl 
ASFF 
12324124124 
opuoiupoiu 
1234 

выход valgrind есть:

[[email protected] 01]$ valgrind --track-origins=yes --tool=memcheck ./1_9 < 1_9.test 
==4890== Memcheck, a memory error detector 
==4890== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==4890== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info 
==4890== Command: ./1_9 
==4890== 
Ready for reading from stdin... 
Reading finished. Here are the results: 
    asdfhjkl 
    ASFF 
    12324124124 
    opuoiupoiu 
    1234 
==4890== Conditional jump or move depends on uninitialised value(s) 
==4890== at 0x400E30: main (in /home/vitaly/prog/study/cpp/01/1_9) 
==4890== Uninitialised value was created by a heap allocation 
==4890== at 0x4C27965: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4890== by 0x400D63: main (in /home/vitaly/prog/study/cpp/01/1_9) 
==4890== 
Cleaning the memory... 
    Deleting: asdfhjkl 
==4890== Invalid read of size 8 
==4890== at 0x400EA0: main (in /home/vitaly/prog/study/cpp/01/1_9) 
==4890== Address 0x5a141d8 is 8 bytes inside a block of size 16 free'd 
==4890== at 0x4C28991: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4890== by 0x400E9B: main (in /home/vitaly/prog/study/cpp/01/1_9) 
==4890== 
    Deleting: ASFF 
    Deleting: 12324124124 
    Deleting: opuoiupoiu 
    Deleting: 1234 
Bye! 
==4890== 
==4890== HEAP SUMMARY: 
==4890==  in use at exit: 0 bytes in 0 blocks 
==4890== total heap usage: 30 allocs, 30 frees, 796 bytes allocated 
==4890== 
==4890== All heap blocks were freed -- no leaks are possible 
==4890== 
==4890== For counts of detected and suppressed errors, rerun with: -v 
==4890== ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 2 from 2) 

UPD: Добавлен вывод отладки. Не могу понять, почему invalid read выдается во время первой итерации в последнем цикле?

+1

Эй, кто голосовал, чтобы закрыть этот вопрос? Это совершенно правильный вопрос. – Andrey

+0

@ Andrey _ «Эй, кто голосовал, чтобы закрыть этот вопрос? ...» Это был я (среди прочих). Возможно, если запрос о неопределенном поведении составляет действительный, исследуемый и отлаженный вопрос о SO, или он должен быть закрыт, либо нажав: 1. Невозможно воспроизвести как из простой/типографской ошибки. 2. Недостаточно усилий для отладки. –

+0

@ πάνταῥεῖ вы проголосовали по причине «должны включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для ее воспроизведения». Он соответствует этому требованию. Я не думаю, что это был самый интересный вопрос, но это было действительно. – Andrey

ответ

4

Одно предположение, что вы пытаетесь получить доступ к удаляемого объекта:

В for: _node = _node->next после delete node;

+0

Где это делается в случае, когда _node равно null? Я не вижу этого. Разумеется, тело цикла не вводится. –

+0

Эта проблема не имеет ничего общего с тем, что она равна нулю. Доступ к _node после его удаления - UB. – drescherjm

+0

Выполнено первое итерационное выражение Poldie, а затем выражение условия. Тело не достигнуто. http://en.cppreference.com/w/cpp/language/for – Andrey