2017-01-29 4 views
0

У меня довольно большая программа с небольшой проблемой памяти. Код работает так, как должен, и я получаю результаты, которые хочу, но я хотел бы избавиться от коррупции. Я побежал вальгрид, но я действительно не понимаю ошибку.Valgrind говорит, что повреждение памяти malloc не используется malloc

Вот что он говорит:

==11295== 
==11295== HEAP SUMMARY: 
==11295==  in use at exit: 72,704 bytes in 2 blocks 
==11295== total heap usage: 19,836 allocs, 19,834 frees, 1,247,711 bytes allocated 
==11295== 
==11295== 0 bytes in 1 blocks are definitely lost in loss record 1 of 2 
==11295== at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==11295== by 0x40197C: grid::setSize(int, int) (grid.cpp:75) 
==11295== by 0x40B9AC: node::node() (node.cpp:17) 
==11295== by 0x4032AF: main (main.cpp:15) 
==11295== 
==11295== 72,704 bytes in 1 blocks are still reachable in loss record 2 of 2 
==11295== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==11295== by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21) 
==11295== by 0x40104E9: call_init.part.0 (dl-init.c:72) 
==11295== by 0x40105FA: call_init (dl-init.c:30) 
==11295== by 0x40105FA: _dl_init (dl-init.c:120) 
==11295== by 0x4000CF9: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 
==11295== 
==11295== LEAK SUMMARY: 
==11295== definitely lost: 0 bytes in 1 blocks 
==11295== indirectly lost: 0 bytes in 0 blocks 
==11295==  possibly lost: 0 bytes in 0 blocks 
==11295== still reachable: 72,704 bytes in 1 blocks 
==11295==   suppressed: 0 bytes in 0 blocks 
==11295== 
==11295== For counts of detected and suppressed errors, rerun with: -v 
==11295== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 1 from 1) 

Единственные указатели Я знаю, что я создаю в функции grid.setSize(), но те все должны быть позаботятся деструктора. Кроме того, первый блок valgrind говорит, что потеряно 0 байт.

Что меня смущает, это второй блок. Я нигде не использовал malloc, и я действительно не знаю, что мне нужно от блока.

Любая помощь приветствуется!

В соответствии с запросом, вот некоторые из кода.

grid.cpp

#include <iostream> 
#include <cstdlib> 
#include <cstddef> 
#include "grid.h" 
using namespace std; 

// initializes the double pointer 
grid::grid() 
{ 
    m_grid = NULL; 
} 

// destroys the 2D game array 
grid::~grid() 
{ 
    for (int i = 0; i < m_width; i++) 
    { 
    delete[] m_grid[i]; 
    } 

    delete[] m_grid; 
} 

cell** grid::getGrid() 
{ 
    return m_grid; 
} 

// returns width 
int grid::getWidth() 
{ 
    return m_width; 
} 

// returns height 
int grid::getHeight() 
{ 
    return m_height; 
} 

// returns radiation level of specified cell 
int grid::getCellRad(const int x, const int y) const 
{ 
    return m_grid[x][y].m_rad; 
} 

int grid::getXRad() const 
{ 
    return m_x_rad; 
} 

int grid::getYRad() const 
{ 
    return m_y_rad; 
} 

// clears grid pointer 
void grid::setGridNull() 
{ 
    m_grid = NULL; 
} 

// creates a grid of size width * height and makes all cells unoccupied 
void grid::setSize(const int grid_width, const int grid_height) 
{ 
    m_width = grid_width; 
    m_height = grid_height; 
    m_grid = new cell* [m_width]; 

    // from left to right 
    for (int i = 0; i < m_width; i++) 
    { 
    m_grid[i] = new cell [m_height]; 

    // from top to bottom 
    for (int j = 0; j < m_height; j++) 
    { 
     m_grid[i][j].m_occupied = 0; 
    } 
    } 
} 

// calculates radiation value for all cells in the grid 
void grid::setRadiation(const int x_coord, const int y_coord, 
    const int rad_mag, const int decay_factor) 
{ 
    m_x_rad = x_coord; 
    m_y_rad = y_coord; 

    // from left to right 
    for (int i = 0; i < m_width; i++) 
    { 
    // from top to bottom 
    for (int j = 0; j < m_height; j++) 
    { 
     // radiation (equals) max radiation (minus) 
     // Manhattan distance between source and current (times) decay factor 
     m_grid[i][j].m_rad = rad_mag - 
     (abs(m_x_rad - i) + abs(m_y_rad - j)) * decay_factor; 

     // minimum radiation 
     if (m_grid[i][j].m_rad < 1) 
     m_grid[i][j].m_rad = 1; 
    } 
    } 

    return; 
} 

// makes a specified cell unavailable 
void grid::setOccupied(const int x, const int y) 
{ 
    m_grid[x][y].m_occupied = 1; 
    return; 
} 

// makes a specified cell available 
void grid::setUnoccupied(const int x, const int y) 
{ 
    m_grid[x][y].m_occupied = 0; 
    return; 
} 

grid& grid::operator=(const grid& g) 
{ 
    m_x_rad = g.m_x_rad; 
    m_y_rad = g.m_y_rad; 
    m_width = g.m_width; 
    m_height = g.m_height; 
    m_grid = new cell* [m_width]; 

    // from left to right 
    for (int i = 0; i < m_width; i++) 
    { 
    m_grid[i] = new cell [m_height]; 

    // from top to bottom 
    for (int j = 0; j < m_height; j++) 
    { 
     m_grid[i][j].m_occupied = g.m_grid[i][j].m_occupied; 
     m_grid[i][j].m_rad = g.m_grid[i][j].m_rad; 
    } 
    } 

    return *this; 
} 

// checks whether specified cell is available 
bool grid::isAvailable(const int x, const int y) const 
{ 
    return !(m_grid[x][y].m_occupied); 
} 

// displays a map of available/unavailable cells 
void grid::printOccupied() const 
{ 
    cout << "--------------------Occupied\n"; 

    // from top to bottom 
    for (int i = 0; i < m_height; i++) 
    { 
    // from left to right 
    for (int j = 0; j < m_width; j++) 
    { 
     cout << (m_grid[j][i].m_occupied ? "1" : "0") << " "; 
    } 
    cout << "\n"; 
    } 
} 

// displays a map of every cell's radiation level 
void grid::printRadiation() const 
{ 
    cout << "--------------------Radiation\n"; 

    // from top to bottom 
    for (int i = 0; i < m_height; i++) 
    { 
    // from left to right 
    for (int j = 0; j < m_width; j++) 
    { 
     cout << m_grid[j][i].m_rad 
     << (m_grid[j][i].m_rad >= DOUBLE_DIGIT ? " " : " "); 
    } 
    cout << "\n"; 
    } 
} 

main.cpp

#include "main.h" 
using namespace std; 

int main() 
{ 
    clock_t start = clock(); 
    double duration; 
    queue<node> frontier; 
    node root; // node that grabs initial puzzle state 
    unordered_map<int, basic_node> node_map; 

    int grid_width, grid_height, x_coord, y_coord, rad_mag, decay_factor, 
     num_alligators, num_turtles, num_trees; 
    string orientation; 

    root.setNumItems(VECTOR_SHIFT + num_alligators + num_turtles + num_trees); 

    if (!getInitialPuzzle(root.getGrid(), root.getItems(), 
     grid_width, grid_height, rad_mag, decay_factor, 
     num_alligators, num_turtles, num_trees, 
     x_coord, y_coord, orientation)) 
    { 
     return -1; 
    } 

    frontier.push(node(root)); 
    breadthFirstTreeSearch(frontier, node_map, num_alligators, num_trees); 

    // put the root in the hash table 
    basic_node r; 
    r.node_id = frontier.back().getID(); 
    r.node_parent = -1; 
    r.node_cost = frontier.back().getItems()[1]. // only the boat has a cost 
     calcItemCost(frontier.back().getGrid()); 
    // no action taken to get here 
    r.node_action_item = '\0'; 
    r.node_action_number = 0; 
    r.node_action_move = '\0'; 

    node_map.insert({r.node_id, r}); 

    int j = 0; 
    while (!frontier.empty()) 
    { 
     ++j; 

     if (frontier.front().isGoal()) 
      break; 

     // only need to check boat, alligators, and turtles 
     for (int i = 1; i < frontier.front().getItems().size() - num_trees; i++) 
     { 
      // only the boat can rotate 
      if (i == 1) 
      { 
       // if the boat can rotate ccw in its own grid 
       if (frontier.front().getItems()[i]. 
        canRotateCCW(frontier.front().getGrid())) 
       { 
        // enqueue a copy of the current node and rotate that boat ccw 
        frontier.push(frontier.front()); 
        frontier.back().getItems()[i].rotateCCW(frontier.back().getGrid()); 

        basic_node b; 
        b.node_id = frontier.back().getID(); 
        b.node_parent = frontier.back().getParent(); 
        b.node_cost = frontier.back().getItems()[1]. 
         calcItemCost(frontier.back().getGrid()); 
        b.node_action_item = frontier.back().getItems()[1].getType(); 
        b.node_action_number = 0; // there's only one boat 
        b.node_action_move = 'N'; // counterclockwise 

        node_map.insert({b.node_id, b}); 
       } 

       // if the boat can rotate cw in its own grid 
       if (frontier.front().getItems()[i]. 
        canRotateCW(frontier.front().getGrid())) 
       { 
        // enqueue a copy of the current node and rotate that boat cw 
        frontier.push(frontier.front()); 
        frontier.back().getItems()[i].rotateCW(frontier.back().getGrid()); 

        basic_node b; 
        b.node_id = frontier.back().getID(); 
        b.node_parent = frontier.back().getParent(); 
        b.node_cost = frontier.back().getItems()[1]. 
         calcItemCost(frontier.back().getGrid()); 
        b.node_action_item = frontier.back().getItems()[1].getType(); 
        b.node_action_number = 0; // there's only one boat 
        b.node_action_move = 'C'; // clockwise 

        node_map.insert({b.node_id, b}); 
       } 
      } 

      // if the boat, alligator, or turtle can move forward 
      if (frontier.front().getItems()[i]. 
       canMoveForward(frontier.front().getGrid())) 
      { 
       // enqueue a copy of the current node and move the item forward 
       frontier.push(frontier.front()); 
       frontier.back().getItems()[i].moveForward(frontier.back().getGrid()); 

       basic_node b; 
       b.node_id = frontier.back().getID(); 
       b.node_parent = frontier.back().getParent(); 
       b.node_cost = frontier.back().getItems()[1]. 
        calcItemCost(frontier.back().getGrid()); 

       // gets B, A, or T for the item that moves 
       b.node_action_item = frontier.back().getItems()[i].getType(); 
       // need to shift for boat and goal, and alligator if necessary 
       b.node_action_number = i - 
        (b.node_action_item == 'B' ? 1 : VECTOR_SHIFT) - // shift 1 if boat 
        (b.node_action_item == 'A' ? 0 : num_alligators); 
       // this will get the movement; one of {U, D, L, R} 
       b.node_action_move = (frontier.back().getItems()[i].getOrientation()); 

       node_map.insert({b.node_id, b}); 
      } 

      // if the alligator or turtle can move backward 
      if (frontier.front().getItems()[i]. 
       canMoveBackward(frontier.front().getGrid())) 
      { 
       // enqueue a copy of the current node and move the item forward 
       frontier.push(frontier.front()); 
       frontier.back().getItems()[i].moveBackward(frontier.back().getGrid()); 

       basic_node b; 
       b.node_id = frontier.back().getID(); 
       b.node_parent = frontier.back().getParent(); 
       b.node_cost = frontier.back().getItems()[1]. 
        calcItemCost(frontier.back().getGrid()); 

       // gets A or T for the item that moves 
       b.node_action_item = frontier.back().getItems()[i].getType(); 
       // need to shift for boat and goal, and alligator if necessary 
       b.node_action_number = i - VECTOR_SHIFT - 
        (b.node_action_item == 'A' ? 0 : num_alligators); 
       // this will get the movement; one of {U, D, L, R} 
       b.node_action_move = (frontier.back().getItems()[i].getOrientation()); 

       // this will get the movement; one of {U, D, L, R} 
       switch (frontier.back().getItems()[i].getOrientation()) 
       { 
        case 'L': 
         b.node_action_move = 'R'; 
         break; 
        case 'R': 
         b.node_action_move = 'L'; 
         break; 
        case 'U': 
         b.node_action_move = 'D'; 
         break; 
        case 'D': 
         b.node_action_move = 'U'; 
         break; 
       } 

       node_map.insert({b.node_id, b}); 
      } 
     } 

     // all possible moves completed for the current state of the board 
     frontier.pop(); 
    } 

    root.getGrid().printOccupied(); 
    cout << endl; 
    frontier.front().getGrid().printRadiation(); 

    duration = double(clock() - start)/CLOCKS_PER_MS; 
    writeSolutions(duration, frontier.front(), node_map, rad_mag, decay_factor, 
     num_alligators, num_turtles, num_trees); 

    return 0; 
} 

и node.cpp

#include <cstddef> 
#include <iostream> 
#include "node.h" 

int node::class_id = 0; 
int node::num_items = 0; 

node::node() 
{ 
    m_grid.setGridNull(); 
    m_grid.setSize(0, 0); 
    m_grid.setRadiation(0, 0, 0, 0); 
    m_id = 0; 
    m_parent = 0; 
} 

node::node(const node& n) 
{ 
    m_grid = n.m_grid; 
    m_items = n.m_items; 
    m_id = ++class_id; 
    m_parent = n.m_id; 

    /*for (int i = 0; i < n.getNumItems(); i++) 
    { 
    m_items[i] = n.m_items[i]; 
    }*/ 
} 

int node::getNumItems() const 
{ 
    return num_items; 
} 

grid& node::getGrid() 
{ 
    return m_grid; 
} 

vector<item>& node::getItems() 
{ 
    return m_items; 
} 

int node::getID() const 
{ 
    return m_id; 
} 

int node::getParent() const 
{ 
    return m_parent; 
} 

void node::setNumItems(const int n) 
{ 
    num_items = n; 
    return; 
} 

void node::setID(const int i) 
{ 
    m_id = i; 
    return; 
} 

void node::setParent(const int p) 
{ 
    m_parent = p; 
    return; 
} 

node& node::operator=(node& n) 
{ 
    m_grid = n.m_grid; 
    m_parent = n.m_parent; 
    m_id = ++class_id; 

    for (int i = 0; i < n.getItems().size(); i++) 
    { 
    cout << "yo\n"; 
    m_items[i] = n.m_items[i]; 
    cout << "hey\n"; 
    } 

    return *this; 
} 

// this will compare the boat and goal locations to determine goal node 
bool node::isGoal() const 
{ 
    bool found = false; 

    // if we don't have 2+, we don't have a goal and a boat 
    if (m_items.size() >= 2) 
    { 
    // item 1 is the boat 
    // back of the boat is in the goal 
    if ((m_items[1].getXCoord() == m_items[0].getXCoord()) && 
     m_items[1].getYCoord() == m_items[0].getYCoord()) 
    { 
     found = true; 
    } 

    else 
    { 
     switch (m_items[1].getOrientation()) 
     { 
     case 'R': 
      if ((m_items[1].getXCoord() == m_items[0].getXCoord() - 1) && 
      m_items[1].getYCoord() == m_items[0].getYCoord()) 
      { 
      found = true; 
      } 
      break; 

     case 'U': 
      if ((m_items[1].getXCoord() == m_items[0].getXCoord()) && 
      m_items[1].getYCoord() == m_items[0].getYCoord() + 1) 
      { 
      found = true; 
      } 
      break; 

     case 'L': 
      if ((m_items[1].getXCoord() == m_items[0].getXCoord() + 1) && 
      m_items[1].getYCoord() == m_items[0].getYCoord()) 
      { 
      found = true; 
      } 
      break; 

     case 'D': 
      if ((m_items[1].getXCoord() == m_items[0].getXCoord()) && 
      m_items[1].getYCoord() == m_items[0].getYCoord() - 1) 
      { 
      found = true; 
      } 
      break; 
     } 
    } 
    } 

    return found; 
} 
+1

Пожалуйста, разместите файл 'grid.cpp' (также main.cpp и node.cpp) с определением класса, конструкторами и деструкторами. Вы называете деструктор из основного? ('new' и' new [] 'оба используют malloc внутренне.) Первая утечка в вашем коде (от« 0 байт в 1 блоке »мы можем предположить, что вы сделали новый с нулевым размером, но не выполнили [соответствующее удаление] (http : //stackoverflow.com/a/1087059), а во-вторых, не настоящая утечка, это всего лишь некоторая память, внутренняя для системы rtld (динамический компоновщик загрузчика). – osgx

+0

Без кода сложно, но вы пытались «очистить» или очистить объектные файлы перед компиляцией? – cpatricio

+0

Где валгринд говорит что-нибудь о «коррупции памяти»? – melpomene

ответ

2

Ключ в кадре стека _dl_init. Это функция инициализации разделяемой библиотеки. Каждый раз, когда загружается общая библиотека, запускается его функция инициализации. Блок памяти, о котором идет речь, был выделен в функции инициализации разделяемой библиотеки.

Общедоступные библиотеки выделяют память для своих внутренних структур данных в своих функциях инициализации. Это библиотека времени выполнения C++, которая, как ожидается, останется загруженной в течение всего жизненного цикла процесса. Таким образом, это не поистине утечка памяти, тем более, что «возможно потерянное» обозначение указывает на то, что valgrind удалось найти указатель на блок памяти где-то.

Однако у вас есть утечка памяти в вашем собственном коде. «определенно потерянный» означает, что это означает: определенно потерянный. Ваш класс просочился в память, и valgrind не нашел ни одного обвисшего указателя на него, иначе он попадет в категорию «возможно потерянных».

+0

Мой вопрос тогда в том, почему он говорит, что 0 байт определенно потеряны. Может ли это просто не учитывать, сколько потеряно? – hockeysaint

+0

@hockeysaint Это из 'm_grid.setSize (0, 0);', который выполняет 'm_grid = new cell * [0];'. Этот указатель никогда не освобождается. – melpomene

+0

Когда вызывается 'm_grid.setSize (0, 0);',? Насколько я знаю, единственный раз, когда я называю 'setSize()', - это когда у меня уже назначена ширина и высота (к ненулевым значениям). Или вы имеете в виду, что единственный указатель никогда не удаляется для любой сетки размера, но двойной указатель есть? – hockeysaint