Sziasztok!
C++ class-okat szeretnék elhelyezni egy dinamikusan lefoglalt memóriaterületen tömbszerűen, egymás után. (Az eredeti környezetben shmget()-tel lefoglalt shared memory, de a példaprogramba malloc-ot írtam az egyszerűség kedvéért.)
A kérdés röviden: Hogyan kell a kostruktort meghívni?
sgyori@ubuntu:~/cppteszt$ cat teszt.cc
#include <malloc.h>
class A {
public: A();
~A();
};
A::A() {
};
A::~A() {
}
class A *p, *p1;
main() {
p=(A*)malloc(10*sizeof(A));
p1=p;
for (int i=0; i<10; i++) {
p1->A();
p1++;
};
};
sgyori@ubuntu:~/cppteszt$ cc -o teszt teszt.cc
teszt.cc: In function ‘int main()’:
teszt.cc:23: error: invalid use of ‘class A’
- 1442 megtekintés
Hozzászólások
class A *p, *p1;
helyett
A *p, *p1;
- A hozzászóláshoz be kell jelentkezni
Köszi, ettől még a probléma megmaradt.
A
p1->A();
utasítást nem hajlandó lefordítani :-(
- A hozzászóláshoz be kell jelentkezni
a ciklus belsejébe pedig:
pl=new A();
- A hozzászóláshoz be kell jelentkezni
Természetesen a pl->A(); helyett
- A hozzászóláshoz be kell jelentkezni
Épp a new hívást akarom elkerülni, mert az új memóriaterületet foglal a heapen, én pedig mindenképpen az előre lefoglalt "shared" területen akarom elhelyezni az objektumaimat, hogy más prcesszekből is elérhetők legyenek.
- A hozzászóláshoz be kell jelentkezni
placement new:
for (int i=0; i<10; i++) {
new (p+i) A;
};
- A hozzászóláshoz be kell jelentkezni
Ez a placement new ígéretesnek tűnik, de gnu c++ 4.1.3 nem hajlandó lefordítani.
A hibaüzenet:
teszt.cc: In function ‘int main()’:
teszt.cc:22: error: no matching function for call to ‘operator new(unsigned int, A*)’
<built-in>:0: note: candidates are: void* operator new(unsigned int)
Mindenesetre a tippet köszönöm, a new utasításnak ezt a formáját nem ismertem.
- A hozzászóláshoz be kell jelentkezni
#include
azaz include memory
- A hozzászóláshoz be kell jelentkezni
Köszi, közben megtaláltam én is.
Egy
#include <new>
megoldotta és jónak is tűnik.
Még egyszer köszönöm mindenkinek, aki segített!
- A hozzászóláshoz be kell jelentkezni
Probald be#include-olni a <memory>-t :-)
Szerk.: ARGH.
- A hozzászóláshoz be kell jelentkezni
Miért is ne csesztem volna el?
pl=new A(); már csak azért is szar volt, mert a pl mutató értéke változott.
(*p1)=A(); -ezt már remélem nem csesztem el
- A hozzászóláshoz be kell jelentkezni
Ez lefordul ugyan, de mindig ugyanaz az objektumpéldány inicializálódik...
Azért köszi, de úgy tűnik a "placement new"-t kerestem.
- A hozzászóláshoz be kell jelentkezni
/o\
Lefoglalsz egy memóriaterületet, az odáig oké, de mi van benne? És csak úgy meghívod a konstruktort direktben?
- A hozzászóláshoz be kell jelentkezni
Úgy szeretnék objektumpéldányokat létrehozni, hogy ezek adatterületei az előzőekben lefoglalt memóriaterületre kerüljenek.
- A hozzászóláshoz be kell jelentkezni
#include <new>
#include <iostream>
using namespace std;
class TC
{
public:
TC( int i );
~TC();
private:
int m_i;
};
TC::TC( int i ) :
m_i( i )
{
cout << "constructor called with " << i << endl;
}
TC::~TC()
{
cout << "destructor called, m_i is " << m_i << endl;
}
int main( int argc, char **argv )
{
void *mem=malloc( sizeof( TC ) );
::new( mem ) TC( 42 );
TC *typedptr( (TC*) mem );
typedptr->~TC();
free( mem );
return 0;
}
egyeb kerdes?
- A hozzászóláshoz be kell jelentkezni
Ha már placement new, akkor inkább:
int main()
{
A* p=(A*)malloc(10*sizeof(A));
new(p) A[10];
...
Csak ne felejtsd el free előtt lefuttatni a destruktorokat...
...
for (int j=0; j<10; ++j)
p[j]->~A();
free (p);
}
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
A helyzet ennél bonyolultabb, mert több különböző (~70) osztály objektumait kellene egy közös területen tárolni, csak a példa kedvéért egyszerűsítettem a programot.
- A hozzászóláshoz be kell jelentkezni
Amugy ez mind szep es jo, meg meg lehet eroszakolni a c++-t es ganyolni nagyokat (c alapu nyelvek nagy elonye) de meg lehetne ezt oldani szebben is: Pl irsz egy allocatort az std::vector-hoz. (amugy amikor kezdtem c++ -t hasznalni C utan, en is igy oldottam meg egy sajat container osztalyban a dolgokat, de akkor meg gozom nem volt rola mi is az az stl...)
- A hozzászóláshoz be kell jelentkezni
Ezzel van egy kis gond. Mármint az allokátorral.
Gondolom azt látod magad előtt, hogy definiálsz egy allokátrot, majd egy ezt használó vektort, az egyik processz push_back-kel, és a cucc megjelenik a másik oldalon.
Ehhez viszont az kéne, hogy mikor processz_1 push_back-et nyom, elérje a processz_2 vektorjának size adattagját, tehát már a vektornak is shared memory-ban kéne lenni...
És ekkor már majdnem ott vagy ahol eddig.
Jobban jársz, ha saját osztályt írsz a dologra...
Arról nem beszélve, hogy ez osztályokra nem is működik rendesen, lásd lent:
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
És én még egy átlagos programozó szintjét sem érem el, csak egy egyszerű mérnök vagyok. Van valakinek egy negyvenötöse??? :-)
- A hozzászóláshoz be kell jelentkezni
Upsz!
A "lásd lent" erre vonatkozott. Semmi beképzelt "hülyékvagytoktiehhez" sugallat nem volt tervbe véve. :)
Csak az a hozzászólás később készült mint a fenti...
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
De ez miert ganyolas? Egy kategoriaval altalanosabb megoldas, mint az allocator. Raadasul ha feluldefinialod a new operatort, akkor az stl (azon resze, ami nincs elore leforditva, tehat a templatek) is a te new-odat fogja hasznalni. Es ez jo. :-)
- A hozzászóláshoz be kell jelentkezni
azert ganyolas mert ha elkerulheto hogy sajat kodot mirjunk meglevo, stabil, agyontesztelt konyvtari kodok (pl stl) felhasznalasa helyett, akkor el kell kerulni. jelen esetben ha stl-t hasznalsz es egy allocatort irsz hozza akkor egy viszonylag egyszeru allocatort kell hibatlanul megirnod. ha nem, akkor egy egesz containert.
hozzateszem nem tudom mi a tenyleges feladat, mert azt a kerdezo nem arulta el, de valoszinu valamit tervezesi szinten rontott el, ha komplett classokat akar processek kozott mozgatni. hogy ez miert nem mukodhet, elottem mar elmondtak paran. azt viszont tarom hogy amennyiben adatokat akar egy specialis memoriateruletre elhelyezni, arra sokkal biztonsagosabb megoldas valamelyik stl container hasznalata sajat allocatorral.
- A hozzászóláshoz be kell jelentkezni
Ez egy sok év alatt többször továbbfejelszt(get)ett rendszer. Jelen állapotában egy szerver és több kliens processz fut, amelyek ugyanazokat az adatokat használják. Az érintett adatok lényegében statikusak, postgresből betöltött többszázezer rekordot tartalmaznak amelyeknek minden processzből elérhetőnek kell lenniük. Indulás után a szerver és a kliens processzek is betöltik ezeket az adatokat és a saját memóriaterületükön tárolják. (Egy jellemző adat: az összes objektum összes adatának elképzelés szerinti tárolására ~35MB osztott memória szükséges.) Arra gondoltam, hogy sok memóriát és a kliensek indulásakor kb 10 másodperc gépidőt spórolhatnék meg, ha a szerver processz betöltés után egy megosztott memóriaterületre töltené az adatokat és a kliens processzek adatbetöltés nélkül egyszerűen hozzákapcsolódnának a megosztott memóriához.
- A hozzászóláshoz be kell jelentkezni
es ehez miert akarsz osztalyokat elhelyezni a shared memoryban? csinalsz valami fejlecet az adatok ele, ami megmondja mi mekkora offszetre van a memoria kezdetetol es feltoltod az adatokat.
nem vadaszunk termonuklearis ballisztikus raketaval nadi poszatara...
- A hozzászóláshoz be kell jelentkezni
Van ~70 class, mindegyik tartalmaz néhány adatmezőt és néhány függvényt. Nem címezhetem át egyenként mindegyiket. Csinálhatnék mindegyikhez egy struktúrát, és az osztály maga csak egy pointert tartalmazna a struktúra kezdőcímére, de ehhez az összes függvényt módosítani kéne. Tovább tartana sörétes puskát reszelni, mint ballisztikus rakétát gyártani.
- A hozzászóláshoz be kell jelentkezni
Amit felvetettél az nem fog működni!
Nevezetesen: tetszőleges osztály berakása a shared memory-ba.
Miért?
Mert ha az osztályod tartalmaz akár egyetlen virtuális függvényt is, akkor minden objektum tartalmaz egy mutatót a vtable-jére.
Ha két processzed van, akkor az elsőben létrehozott objektumok az első processz saját mem területén található vtable-re hivatkoznak, tehát amint használni akarod a másik proszesszből az objektumot SEGFAULT-ot kapsz.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21251
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
Ez elgondolkodtatott... Arra felkészültem, hogy az osztályok nem tartalmazhatnak pointereket, mert azok az egyes processzek címterében mást jelentenének, de utána kell néznem, hogy vannak-e virtuális függvények az érintett osztályokban :-((
- A hozzászóláshoz be kell jelentkezni
Jah, es ezen nem is igazan lehet segiteni
- A hozzászóláshoz be kell jelentkezni
Szerencsére sikerült megoldanom, most van egy kis időm, leírom vázlatosan...
A linker -M kapcsolóját használva látható volt, hogy a "vtable" területeket a ".rodata" nevű szekcióba helyezi el, mégpedig a parancssorban felsorolt ".o" object file-ok sorrendjében, a szekció elejétől kezdve. Mivel ez a sorrend mindkét program linkelésekor egyforma volt, csak azt kellett biztosítani, hogy a ".rodata" mindkét programban azonos címen kezdődjön és máris mindkét programban érvényesek lettek az egyes objetumpéldányok "vtable" pointerei. A linker "--section-start" kapcsolójával megadtam a kívánt kezdőcímet és remekül futnak a programok. (Igaz a linker scriptet módosítani kellet, mert kevésnek találta program "header"-ek számát.)
Mindenkinek köszönöm a segítséget!
- A hozzászóláshoz be kell jelentkezni
Jajj!!!
Isten irgalmazzon annak, aki ezt a forrást egyszer átveszi tőled...
Isten irgalmazzon annak, akinek ezt egyszer portolnia kell más oprendszerre, más fordítóra, vagy csak egyszerűen a fordítóprogram következő verziójára.
(Mindenképpen dokumentáld, akkor is, ha sose nyúl hozzá más rajtad kívül. 5 év múlva nem lesz ilyen egyértelmű. :) )
Legalább megérte? (Gyorsabb lett?)
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
- A hozzászóláshoz be kell jelentkezni
Bocs, de nem követtem tovább a threadet. Természetesen gyorsabb lett, kb 3 nagyságrenddel :-)))
~15sec helyett ~50msec
- A hozzászóláshoz be kell jelentkezni