Forums -> Глюкодром -> туплю в c++
| Full Version

Lexus
Имеетъся 2 класса (Cell, Node) и основная програмулина da.cpp

В классах Cell и Node надо сделать поинтеры друг на друга. Гугл сказал нужно Forward referenz делатъ, но что-то я так и не допёр :(

Исходники таковы:

cell.h
CODE

#ifndef _cell_h_
#define _cell_h_
#include "Node.h"

class Cell {

public:
int status; //0-int,1-bdry,2-outside
double _value;
Cell * Neighbours[2];
Node * NodePointer;

Cell(double value);
Cell();
~Cell();

};

#endif /* _cell_h_ */

cell.cpp
CODE
#include <iostream>
#include <list>
#include <map>
#include <vector>
#include <fstream>
#include "Cell.h"

using namespace std;


Cell::Cell(double value): _value(value){};
Cell::Cell(){};
Cell::~Cell(){};


Node.h
CODE
#ifndef _node_h_
#define _node_h_

#include "Cell.h"

class Cell;
class Node {

public:
int _eventtyp; //0 - Node, 1,2,... - leaf
bool _isleaf;

//samplingtest

Cell *_CellPointer; //Null - if Node
Node * Neighbours[2];
double _NodeRate;
double _NodeValue;
int _Num;
//double _NodeRightRate;
Node *_ParentNode, *_nLeft, *_nRight;
Node(int Num,double NodeValue, double NodeRate, bool isleaf);
Node(Node* pLeftChild, Node* pRightChild);
Node();
    ~Node();
inline double getRate() {return _NodeRate;}
inline bool operator <(const Node &other) const{return _NodeRate<other._NodeRate;}

};



#endif /* _node_h_ */

Node.cpp
CODE
#include <iostream>
#include <list>
#include <map>
#include <vector>
#include <fstream>
#include "Node.h"
//#include "Cell.h"

using namespace std;

Node::Node(int Num,double NodeValue, double NodeRate, bool isleaf):  _Num(Num),_NodeValue(NodeValue),_NodeRate(NodeRate),_nLeft(NULL),_nRight(NULL), _isleaf(isleaf)
{
_eventtyp=0;
//_NodeRightRate=_NodeRate;

}
Node::Node(Node* pLeftChild, Node* pRightChild): _NodeRate(pLeftChild->_NodeRate+pRightChild->_NodeRate),_nLeft(pLeftChild),_nRight(pRightChild),_isleaf(false)
{
//_NodeRightRate=pRightChild->_NodeRate;
}

Node::Node(){

_CellPointer = new Cell;

};
Node::~Node(){};

В DA создаётъся обект Node и Cell и поинтерывают друг на друга.

Ну что-то я запутался во всём этом перекрёстном поинтерование.
Заранее спасибо за помощь
Set
Forward declaration это, пример http://www.adp-gmbh.ch/cpp/forward_decl.html

#include "Node.h", #include "Cell.h" - друг в друга не надо, просто:

CODE
class Cell;
class Node {

CODE
class Node;
class Cell {

Указывается, что есть такой класс, а определение его будет потом.
Lexus
Странно как-то вышло. Visual Studio компилирует и всё пашит, г++ ругается:
: undefined reference to

Пример по ссылке тоже не компилиться g++
Lexus
Проблема решена. не знал, что компайлеру нужно каждый файл указывать как апраметр :(
FiL
QUOTE (Lexus @ 14-11-2010, 06:33)
Проблема решена. не знал, что компайлеру нужно каждый файл указывать как апраметр :(
makefile писать надо.
Lexus
QUOTE (FiL @ 14-11-2010, 14:58)
QUOTE (Lexus @ 14-11-2010, 06:33)
Проблема решена. не знал, что компайлеру нужно каждый файл указывать как апраметр :(
makefile писать надо.
Да тут засада, по крайней меря для меня :) Пишу под виндой, а запускаться всё будет под салярисом. Поэтому я даже хз куда этит makefile и как его едят :(
FiL
куда - понятно. Рядом с cpp и h файлами. А вот как его писать - тут я тебе не помошник. Но ты уже начинай разбираться, ибо если прокт вырастет за пределы 3-х файлов то по-любому придется. А тренироваться лучше на кошечках :)
Lexus
Дело идёт дальше. Уже есть картинки :)

user posted image

QUOTE
if(currentNode2D->_CellPointer->Neighbours[2]!=NULL)
{
currentNode2D->_CellPointer->Neighbours[2]->NodePointer->_NodeRate=fabs(dh2D(currentNode2D->_CellPointer->Neighbours[2]));
Tree2D->UpdateRate(currentNode2D->_CellPointer->Neighbours[2]->NodePointer);
}
if(currentNode2D->_CellPointer->Neighbours[3]!=NULL)
{
currentNode2D->_CellPointer->Neighbours[3]->NodePointer->_NodeRate=fabs(dh2D(currentNode2D->_CellPointer->Neighbours[3]));
Tree2D->UpdateRate(currentNode2D->_CellPointer->Neighbours[3]->NodePointer);
}
if(currentNode2D->_CellPointer->Neighbours[0]!=NULL)
{
currentNode2D->_CellPointer->Neighbours[0]->NodePointer->_NodeRate=fabs(dh2D(currentNode2D->_CellPointer->Neighbours[0]));
Tree2D->UpdateRate(currentNode2D->_CellPointer->Neighbours[0]->NodePointer);
}
if(currentNode2D->_CellPointer->Neighbours[1]!=NULL)
{
currentNode2D->_CellPointer->Neighbours[1]->NodePointer->_NodeRate=fabs(dh2D(currentNode2D->_CellPointer->Neighbours[1]));
Tree2D->UpdateRate(currentNode2D->_CellPointer->Neighbours[1]->NodePointer);
}

-> здесь

Так как всё будет бегать на квадкоре, то хотелось бы эти операции замультрейдить и где "здесь" удастовериться, что трейды отработали, продолжить дальше отрабстывать код.
С трейдами ниразу ничего не делал, на что стоит обратить внимание и как их использовать?
Lord KiRon
QUOTE (Lexus @ 18-11-2010, 13:49)
Так как всё будет бегать на квадкоре, то хотелось бы эти операции замультрейдить и где "здесь" удастовериться, что трейды отработали, продолжить дальше отрабстывать код.
С трейдами ниразу ничего не делал, на что стоит обратить внимание и как их использовать?
Э... подожди годика так 2-3, поднаберись опыта, в принципе в работе с потоками ничего сложного нет, но не с наскока же...
Кстати, глядя на картинку - рекомендую IPP: http://software.intel.com/en-us/articles/intel-ipp/
думаю тебе прегадится, да и все операции там уже внутри мультистредные и мультикорные.
К тому же есть версия и для винды и для Линикса.
FiL
дык ему-то надо под солярис :)
Lexus
QUOTE (Lord KiRon @ 18-11-2010, 16:40)
Э... подожди годика так 2-3, поднаберись опыта, в принципе в работе с потоками ничего сложного нет, но не с наскока же...
Нужно именно в с++ и ждать некогда, это часть моей будушей дипломной. Т.е. оно и так работает, но у меня будет часть отведена под оптимайзинг и оно нужно :))))
Lord KiRon
QUOTE (FiL @ 18-11-2010, 18:40)
дык ему-то надо под солярис :)
А в солярисе я не копенгаген, там хоть beginthread работает или все через задницу fork?
Lexus
а можно это как-то проверить? Какая-нибудь минипрожка, я профу бы скинул, чтоб он под солярисом попробывал бы скомпилировать.
Lord KiRon
Гугл наше все:
http://condor.depaul.edu/~dmumaugh/readings/handouts/CSC343/unixthreads.html
Lexus
QUOTE (Lord KiRon @ 18-11-2010, 22:15)
Гугл наше все:
http://condor.depaul.edu/~dmumaugh/readings/handouts/CSC343/unixthreads.html
Спасибо. Есть ешё вопрос. У меня объект Tree2D, в нём функция UpdateRate. Тредами я запускаю эту функцию 4-5 раз. Может такое быть, что будет ешё медленей из-за того, что все на один объект кидаються?
Lord KiRon
QUOTE (Lexus @ 18-11-2010, 23:24)
QUOTE (Lord KiRon @ 18-11-2010, 22:15)
Гугл наше все:
http://condor.depaul.edu/~dmumaugh/readings/handouts/CSC343/unixthreads.html
Спасибо. Есть ешё вопрос. У меня объект Tree2D, в нём функция UpdateRate. Тредами я запускаю эту функцию 4-5 раз. Может такое быть, что будет ешё медленей из-за того, что все на один объект кидаються?
Может.
Вообще потоки это не гарантия что будет быстрее, если не понимать что делать скорее гарантия того что будут проблемы, лучше запускай всего один (второй) и в нем обновляй по таймеру. И про синхронизацию не забудь а то будет весело.
FiL
QUOTE (Lexus @ 18-11-2010, 16:24)
QUOTE (Lord KiRon @ 18-11-2010, 22:15)
Гугл наше все:
http://condor.depaul.edu/~dmumaugh/readings/handouts/CSC343/unixthreads.html
Спасибо. Есть ешё вопрос. У меня объект Tree2D, в нём функция UpdateRate. Тредами я запускаю эту функцию 4-5 раз. Может такое быть, что будет ешё медленей из-за того, что все на один объект кидаються?
параллельно запускать функции, работающие над одним и тем-же объектом... боясь, что будет только хуже. Или блокировки замучают или (если блокировки правильно не сделать) вообще хрен знает что получится.
Lexus
Напоролся на след. грабли.

Имеется пара файлоф-калссов. Под виндой компилиться, под линуксом тоже. В солярисе ругается на каждую строчку. делал даже "хелло ворлд" - под виндой и линуксом идёт, под солярисом орёт. Как выяснилось ему не нра переходы строк. Так как если это файло открыть под солярисом, что-то измеить и сохранить. То это же перестаёт компилиться под виндожсом. Говорит, что не одинаковые переходы строк. Можно как-то сделать всё посовместимей?
VxWorks
В винде переход строк CR,LF а в линуксах только LF.

Есть IDE, которые позволяют менять тип перехода строк в зависимости от типа софта.

Из простых, под винду, есть такой Emeral Editor, к которому можно подцепить makefile и все такое. Этот редактор понимает линуксовые переходы строк. Вопрос только в том, поймет ли их твой toolchain :)

ЗЫ: только сегодня мне пришлось решать задачу распараллеливания на два процессора. Вернее, на процессор и сопроцессор. То еще счастье, надо заметить :(
Lexus
А почему тогда под линуксом нормально компилируется, а пот солярисом орёт.
Во всех случая г++
VxWorks
Может, линукс к этому более пофигистично стал относиться, кто его знает :)
Lexus
попробую ту програмулинку.
izanoza
Командная строка тебе в помощь:
dos2unix
unix2dos
Lexus
QUOTE (izanoza @ 12-02-2011, 19:17)
Командная строка тебе в помощь:
dos2unix
unix2dos
Класс, спасибо.

Только заметил такой прикол. На некоторых файлах не до конца срабатывала прога. На них было вариантом открыть под маком в TextWrapper там выбрать юникс и UDF-8, По умолчанию был какой-то UDF-8 BOM.

Если изначально такое сделать, без дос2юникс, то всёравно были ошибки. Теперь засунул в юниксовском формате всё в студию и теперь пашит как на винде, так в солярисе.

Lexus
Опять ламерский вопрос:)))

CODE
2 2 2 1.85451 1.50428 1.44898 -0.1 1.39533 -0.1 1.35463 1.3364 1.3189 1.30166 1.28417 1.26619 1.24743 1.22461 1.17859 1.14986 1.1402 1.13277 1.12592 1.11947 1.11339 1.10758 1.10205 1.09674 1.09164 1.08674 1.08196 1.07733 1.07283 1.06844 1.06414 1.05992 1.05577 1.05171 1.04765 1.04366 1.0397 1.03576 1.03184 1.02793 1.02401 1.02008 1.01614 1.01217 1.00816 1.00411

имеется файлик с такими данными, надо его в ся считать в double array.
Как ничего не нашёл я, как парсить:(
Set
http://bytes.com/topic/c/answers/618936-how-do-i-split-char-array-c
Lexus
QUOTE (Set @ 21-05-2011, 00:29)
http://bytes.com/topic/c/answers/618936-how-do-i-split-char-array-c
ооо, супер. спасибо!!!
Lexus
Ламерствую дальше )))

Имеется класс Tree. В мэйн части проги в начале создаются порядка 10000 обектов вида Node. Пихаются в Tree потом вызывается команда
Tree2D->BuildTree();

После идёт очень мучительная симуляция в while блоке, в которй Tree2D используется и его нужно через определённые интервалы времени или проходов перестраивать. делается это по средствам: Tree2D->BuildTree();
Но прога вылетает через некоторое кол-во обновлений, так как память с 6мб выжирается до 500-700мб. Если Билдтри не делать, то память не жрётся.
Вопрос в том, как делать ребилд дерева без зажирания памяти.


CODE
#include <iostream>
#include <list>
#include <map>
#include <vector>
#include <fstream>
#include "Node.h"


using namespace std;


class Tree {
public:

list<Node*> _NodeList;
list<Node*> _TreeList;
multimap <double,Node*> _WorkList;
list<Node*>::iterator it;
Node n;

void AddNode(Node* NewNode) {

_NodeList.push_back(NewNode);

};

inline void BuildTree(){

_WorkList.clear();
_TreeList.clear();



for (it = _NodeList.begin(); it != _NodeList.end(); it++)
{
n=**it;
_WorkList.insert(pair<double,Node*>(n.getRate() ,*it));

}
_TreeList = _NodeList;
//cout<<"B: "<<_TreeList.size()<<endl;


while(_WorkList.size()>1)
{

multimap<double, Node*>:: iterator map_it = _WorkList.begin();
Node *pFirstNode = map_it->second;
_WorkList.erase(map_it);
map_it = _WorkList.begin();
Node *pSecondNode = map_it->second;
    _WorkList.erase(map_it);
    Node *pNewNode = new Node(pFirstNode,pSecondNode);
    pFirstNode->_ParentNode=pNewNode;
    pSecondNode->_ParentNode=pNewNode;
    _WorkList.insert(pair<double,Node*>(pNewNode->getRate(),pNewNode));
    _TreeList.push_back(pNewNode);
}

_TreeList.back()->_ParentNode=0;



};

inline void UpdateRate(Node* ChangedNode){

if(ChangedNode->_NodeTyp==-2) return;


Node* next = ChangedNode->_ParentNode;
bool ParentNotNull=true;
while(ParentNotNull)  //0xCDCDCDCD Allocated in heap, but not initialized
{
next->_NodeRate=next->_nLeft->getRate()+next->_nRight->getRate();
ParentNotNull = (next->_ParentNode!= 0) ? true : false;
next=next->_ParentNode;

}


};


Tree(){};
~Tree();
};

boriskin
Иметь на каждый new соответствующий delete, который ьудет подчишать выделенную память как только она становится не нужна.
Lexus
QUOTE (boriskin @ 10-06-2011, 22:26)
Иметь на каждый new соответствующий delete, который ьудет подчишать выделенную память как только она становится не нужна.
т.е. при вызове
_WorkList.clear();
_TreeList.clear();

из List не удаляют объекты с памяти, а просто удаляются со списка?

Как бы так сказать ,я не совсем представляю, где delete вставлять)))))

Set
Пройдись циклом по обеим спискам и delete все объекты. Только потом clear(). Возможно где ещё в коде надо объекты удалять... не разобрать. А вообще выкинуть нафиг этот c++ :D:
Lexus
QUOTE (Set @ 11-06-2011, 01:23)
Пройдись циклом по обеим спискам и delete все объекты. Только потом clear(). Возможно где ещё в коде надо объекты удалять... не разобрать. А вообще выкинуть нафиг этот c++ :D:
да я бы с радостью. Но надо в нём)))

Симуляция длится примерно 2000-3000 сек, За это время эта команда вызывается уйму раз))) Дабы структуру дерева оптимировать.
память жрётся только при вызове этой команды :(
Спасибо за совет, буду пробывать!!!
Lord KiRon
QUOTE (Lexus @ 10-06-2011, 23:03)
QUOTE (boriskin @ 10-06-2011, 22:26)
Иметь на каждый new соответствующий delete, который ьудет подчишать выделенную память как только она становится не нужна.
т.е. при вызове
_WorkList.clear();
_TreeList.clear();

из List не удаляют объекты с памяти, а просто удаляются со списка?

Как бы так сказать ,я не совсем представляю, где delete вставлять)))))
Смотри, clear очищает только список , но если ты засовывал в список элокированые поинтеры а потом вызвал clear то они "теряются".
Все что тебе нужно это для каждого списка перед вызовом clear пройтись по всему списку , что то типа:
CODE
for (it = _WorkList.begin(); it != _WorkList.end(); it++)
{

}
и удалить каждый п[оинтер в каждом элементе.
Lexus
Спасибо!!! Вот так из математиков становятся програмистами))))))) хоть и хреновыми)))))
FiL
вообще судя по мануалу clear вызывает деструктор у каждого элемента перед его удалением. Так что по идее память должна освобождаться.
LExus, ты проверь, у тебя деструктор память освобождает или где.

P.S. я далеко не спец в сях, но что-то меня сильно смущает эффективность данного кода. Неужто перестроить списки нельзя как-то без удаления и создания с нуля? Уж очень оно странно.
Lexus
У меня есть определённые обекты (Cell). в них значения дифф.уравнения. Созфаётся huffman tree где Nodes содержат пропизводные или другие оператроы от уравнений (rate). хуффмантри используется для семплинга элемнтов. Учитывая его структуру доступ к элементам с наибольшей rate намного короче, чем если бы я это делал в бинарном дереве или просто в массиве. Учитывая что уравнение меняется во время симуляции, нужно перестраивать дерево, дабы оптимайзить скорость доступа.
До этого было у меня без
_WorkList.clear();
_TreeList.clear();
но у меня было макс. 400 nodes, сейчас проблема 2D со 100 Nodes, отсюда 100*100 в дереве. И оно уже вылетает от обжорства.

A как проверить, высвобождает или нет?
Set
http://stackoverflow.com/questions/307082/cleaning-up-an-stl-list-vector-of-pointers

Как красиво можно чистить списки. :)
Lord KiRon
QUOTE (FiL @ 11-06-2011, 16:56)
вообще судя по мануалу clear вызывает деструктор у каждого элемента перед его удалением. Так что по идее память должна освобождаться.
Если в список добавлен обьект - да, а если поинтер на обьект то нет.
boriskin
QUOTE (FiL @ 11-06-2011, 09:56)
вообще судя по мануалу clear вызывает деструктор у каждого элемента перед его удалением. Так что по идее память должна освобождаться.
У raw указателя нет деструктора, очищающего указываемую память. ДЛя этого надо auto::ptr или другие варианты обертки указателя с reference counts пользовать.
boriskin
QUOTE (Lexus @ 11-06-2011, 14:48)
A как проверить, высвобождает или нет?
Если под Линуксом/Юниксом - гонять memory leak tools, ченить типа valgrind (или как оно там), если под виндой - то в дебаге в output будет вываливать всю инфу о утечках, если повезет - то даже с указанием на место в коде.