Tomb meret valtozobol

 ( sza2king | 2013. január 15., kedd - 16:16 )

Hi,

Az alabbi dolgot szerettem volna csinalni Visual Studio 2005-os C forditoval (nem uj, de ez van hivatalosan):

int a = 5;
char array[a];

de ezt mondja:

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2133: 'array' : unknown size

Ugyanez egy jelenlegi gcc-vel (4.4) minden extra parameter nelkul felordul.

Meg lehet ezt valahogy javitani? - Ugy ertem, lehet, hogy valami kapcsoloval mukodne?

Koszi,

/sza2

Szerk:

Nem az

int a = 5;
char *array = malloc(a);

megoldassal.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

a "variable-length arrays" csak ISO-C99-ben van benne (a gcc pedig C90-ben is elfogadja, illetve c++ -ban).
A visual studio C90 fordító, így malloc nélkül ez nem fog működni neked.

Koszi.

Ezek szerint a Visual Studio-nal nem lehet bekapcsolni, hogy elfogadja?

/sza2

Ennyire nehéz a malloc?
--
HUPbeszolas FF extension

ha adott fgv -n belűl használod csak és az több ponton kiléphet, akkor inkább macera, mert fel kell szabadítanod minden kilépési pont előtt (vagy használhadsz ronda megoldásokat, pl.: goto;))

alloca() válasz minden problémádra.

--

Megnezem.

Koszi,

/sza2

jogos, errol meg is feledkeztem:)

Vagy használsz 1 kilépési pontot.
--
HUPbeszolas FF extension

Vagy csinálsz egy másik (belső) függvényt, abba belerakod a "sok ponton kiléphet" algoritmust, és a külső függvény végzi a legfoglalást és felszabadítást.

Csak akarat kérdése az egész - nem akarásnak nyögés a vége...

#define die(x) \
if(a) { free(a); } \
return x;

--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

POSIX a C standarddal egyetértésben azt mondá a free(ptr)-ről, hogy "If ptr is a null pointer, no action shall occur."

Az semmi, én olyanokat találtam kódokban, élesben használt kódokban, hogy

if (ptr == 0)
delete ptr;

----
India delenda est.
Hülye pelikán

Egy forditasi idoben tudodd meretu tombot kell letrehoznom. Inkabb nem bonyolitam dinamikus memoriafoglalassal.

Szoval nem, nem nehez a malloc, viszont felesleges.

/sza2

Egy forditasi idoben tudodd meretu tombot kell letrehoznom.

Akkor "#define" is your friend.

Van, hogy malloc nem megengedett, pl. egyes beagyazott rendszereknel.
Amugy csak szolok, hogy a malloc() egy lassu muvelet, sot a free() is lassu, cserebe a stack-en valo foglalas nagyon gyors.

Raadasul malloc()-ot manapsag (C++11) csak a 8-bites kezdok hasznalnak (kiveve nagyon ritka eseteket): vannak kontenerek, pl vector (osidok ota). Van ezen kivul unique_ptr es shared_ptr. Olyanna lett, mint a goto: neha kell, de nagyon meg kell indokolni.

Szerintem egy modern C++ coder manapsag nem irja le, hogy malloc, csak ha nagyon nagy baj van (ertsd szar a kodbazis, rosszul terveztek meg a memoria allokocios strategiat).

A stack-en altalaban tudjuk a max meretet a tombnek, es azt foglaljuk, eszben tartva, hogy a stack kicsi.

Bocsi, most latom, hogy ez C.

Sorry.

nem, sehogy sem fog menni, csak malloc-al

Mindenképpen változónak (értsd: több értékadást elviselőnek) kell lennie annak a változónak? Mert ha nem, akkor dinamikus memóriafoglalás nélkül 2 megoldást is látok a problémára, az egyik C, a másik C++:

//C
#define A 5
char array[A];

//C++
const int a=5;
char array[a];

Egyszer van ertekadas, a fuggvenyek elejen, utana nem valtozik.

Igazabol valami iyesmit akartam:

fgv1() {
  int length = 5;
  char array[length];
  ...
  sendsomething(device, array, length);
}

fgv2() {
  int length = 10;
  char array[length];
  ...
  sendsomething(device, array, length);
}

fgvN() {
  int length = 1;
  char array[length];
  ...
  sendsomething(device, array, length);
}

/sza2

És mi ezen a nehéz?

#define arraydefine(_array,_length,length) \
int _length = length; \
char _array[length]

fgv1() {
arraydefine(array, length, 5);
...
sendsomething(device, array, length);

fgv2() {
arraydefine(array, length, 10);
...
sendsomething(device, array, length);

Ha a fuggveny elejen van mind a ket valtozo definialva, miert nem tudod beutni azt a ketto szamot megegyszer?

Mivel utana vegig a length valtozoval szamolsz, igy ha modositani kell, egy darab kozponti helyen kell modositani, igaz, ket sorban. Nem akkora hibalehetoseg...7

A masik: miert fazunk az alloca() -tol?
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

alloca-t en kerulnem, de ez egyeni velemeny

--
NetBSD - Simplicity is prerequisite for reliability

5-10 int meretu tombokhoz szerintem megfelelo lehet. A peldakodban nincs ennel tobb. Vagy valami architekturalis megfontolas all mogotte?
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Ha egy alapvetoen specialis esetekre kitalalt eszkozt (ez itt most az alloca) elkezdesz esz nelkul hasznalni, akkor konnyen kialakulhat az a bad practice, hogy mindenhol ezt hasznalod.
Foleg ugy, hogy nem irod oda kommentben, hogy
// Mivel 5 elemu a tomb, ezt meg allokalom a stacken

Aztan kesobb valaki fogja a kododat, esznelkul masol belole, meg se nezi, mit csinal a kod (ha hrgy84-nek jo volt, nekem is jo lesz), es megtanulja, hogy hat az alloca az milyen jo dolog, majd nekiall a stacken allokalni hatalmas tomboket.

A szakmaban nagyon sokszor viselkednek igy, foleg a kezdok: nem akarja megerteni amit csinal, csak mukodjon valahogy.
Aztan ebbol ki is alakulnak a rossz szokasok sajnos, amiket kiirtani nagyon nehez.

Azt a technikai dolgot mar emliteni sem akarom, hogy az alloca hivasa eredmenyezhet nem definialt viselkedest (amikor eppen stack overflow tortenik), azaz hibakezelest nem tudsz csinalni.

Egy eszkoz hasznalatatol nem felni kell, hanem megtanulni hasznalni.

Ha megprobalsz effektiv kodot irni, sok esetben az a vege, hogy valami specialis problemara egy specialis megoldast alkalmazol, amit nem lehet jokerkent hasznalni barhol. Ez esetben lehet batran kommentezni, foleg ha attol felsz, hogy mas vakon "atemeli" ill. valtoztatja a kododat. Ha valaki ezt ennek ellenere megteszi, akkor vegyuk ugy, hogy ez is a tanulasi fazis resze ;)

Hibakezelest akkor sem tudsz csinalni, ha alloca() helyett egy lokalis tombot hasznalsz, az ugyanugy felzabalhatja a stackedet. Emiatt kar felni tole.

Viszont toredelmesen bevallom, alloca()-t en meg az eletben nem hasznaltam lol

Nem felek en hasznalni, csak 1. nem lehet batran kommentezni, hanem KELL. Pont azert, hogy aki fel fogja hasznalni a kodot, az ne tanuljon meg semmi bad practice-t. 2. Vegyuk ugy, hoy ez a TANITASI fazis resze.

Miert ugy tortnik a programozas megismerese, elsajatitasa, mintha a kozepkorban elnenk?
A diak ellesi a nagy mesterektol a peldakat, es a sajat (es mas) karan tanulja meg, hogy valoszinuleg talan mi az, ami nem lesz rossz (nem azt, hogy mi az, ami helyes).

Nezd, engem a megbizoim azert fizetnek meg jol, mert azt varjak el, hogy en tudjak jol programozni es meg veletlenul sem azt, hogy megtanitsak olyanokat, akikre nincs eleg penzuk :p Szomoru lenne, ha abbol kellene kiindulnom, hogy baj lehet belole, ha egy lusta es kepzetlen(ebb) programozo latja (masolja, modositja, ...) az adott kodomat. Igy sosem irhatnek inline asm kodot, mert jajj mi lesz, ha senki sem _akarja_ megerteni (hiszen asm ismeret meg veletlenul sem varhato el egy C/C++ programozotol :p), vagy szamuzhetnem a longjmp()-ot is a kellektarambol, mert jajj mi lesz, ha rossz kezekbe kerul.

Nem, az alloca()-t nem _kell_ kommentezni, minthogy a malloc()-nal sem irod oda, hogy "free()-t is kell majd hivni am!". Az alloca() dokumentacioja szabadon elerheto, ha valaki olvassa a kodot es nem erti, elvarhato, hogy nezzen utana. Ha ezt nem teszi, akkor sosem lesz jo programozo, csak egy "betanitott munkas". Amiert erdemes az alloca()-t kommentezni, az inkabb az, hogy miert a stack-en allokalsz es miert nem a heap-en ...

Egyebkent az "alloca() az ordog muve es tuzzel-vassal kuzdeni kell ellene" mentalitas inkabb a kozepkort idezi, mar bocsanat :p

Egyetertek. Ha egy uj dolognal valaki nem hajlando dokumentaciot olvasni, hanem esz nelkul kezdi el hasznalni, azt paros labbal kell kirugni mindenhonnan, mert az csapnivalo programozo. Tekintet nelkul arra, hogy kezdo-e vagy sem.

Tobben tudjak itt rolam, hogy en nem igazan vagyok halado programozonak nevezheto, erosen a kezdo kategoriaba mozgok, foleg C/C++ teruleten, amihez kb. lovesem sincs, pedig ezt-azt azert csinaltam mar benne. De ha en latok egy ismeretlen fuggvenyt/osztalyt/barakarmit, akkor ragooglezok, hogy mi a kutyafule az. Es ha valaki meggooglezza az alloca-t, szerintem pont eleg oldalt fog talalni, ahol le van irva, hogy "Use with caution".

Ezzel egyutt azert annyiban egyet ertek persicsb-vel hogy annyit illik fole irni, hogy miert nem malloc. Nem azt, hogy a stacken foglalunk, mert az az alloca dokumentaciojabol kiderul. Azt sem, hogy pici a tomb, mert az meg a parameterebol derul ki. Hanem azt, hogy miert dontottunk a malloc helyett e mellett (akar csak azt, hogy a fgv tul sok ponton lephet ki, es nem egyszeru a kozos kilepesi pont megteremtese).
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Nem ertem mi ertelme az alloca()-nak. Most komolyan.
A stack merete veges (es kicsi). Foglald le a stack-en a maximum hasznalt meretet.

Tehat, ahelyett, hogy ptr = alloca(n)

if (n > MAX_VALUE) {
error();
}
uint8_t ptr[MAX_VALUE];

He? Irtam en, hogy hasznald? Vagy hogy hasznaltam erre es erre? ;)

Bocsi, de ezt irtad:
"Egyebkent az "alloca() az ordog muve es tuzzel-vassal kuzdeni kell ellene" mentalitas inkabb a kozepkort idezi, mar bocsanat "

Nekem ebbol ugy tunik, hogy a partjat fogod.

A "minek van ez" es a "abszolut kiralysag" kozt nalad nincs semmi? Nem lehet valaminek a letjogosultsagat elismerni anelkul, hogy a partjat fognam?

Szerintem sem kell tuzzel-vassal uldozni, boszorkanyokat a kozepkorban volt szokas megegetni, ma meg mar allitolag tilos. Ettol viszont meg nem valtozik az, hogy ovatosan kell hasznalni.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Jol van na.

Csak a teljesség kedvéért, a makrós megoldás C++-ban:

template <int L>
void fgv()	//nem volt típus megadva
{
	int length = L;	//csak a meglévő kód miatt
	char array[L];

	sendsomething(device, array, length);
}

int main()
{
	fgv<5>();	//fgv1
	fgv<10>();	//fgv2
	fgv<1>();	//fgvN

	return 0;
}

Az igazi szep C++ megoldas inkabb hasznal valamilyen STL containert.

Gyanítom az egyes fgv változatok között az eredeti példában nem csak a tömb mérete volt az eltérés, ergo a te verziód nem megoldás semmire...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Akkor már használnál std::array-t...
----
India delenda est.
Hülye pelikán

+1 lehetőség:
elágazás a méret szerint, kis méretnél lokális változó, nagyobbnál malloc; értelemszerűen a végén csak akkor kell felszabadítás, ha volt malloc. (Ja, és a 'függvény közepéből return' dolgot hanyagoljuk, ronda gányolás;)

void fun (int n)
{
    char sbuff [256];
    char *p0;
    BOOL fAlloc;

    if (n > sizeof (sbuff)) {
	p0 = malloc (n);
	fAlloc = TRUE;
    } else {
	p0 = sbuff;
	fAlloc = FALSE;
    }
    ...
RETURN:
    if (fAlloc) free (p0);
}

Nem mindig lehet egypontos kilepest csinalni. Ha kicsit is bonyolultabb a dontesi fa, akkor mar atlathatatlan kod keletkezik.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Evvel mi mellett szeretnél érvelni? Hogy evvel az erővel sose használjunk malloc-ot, vagy sose használjunk elágazásokat? :) Egy kód bonyolultsága és átláthatósága nem teljesen függ egymástól.

Amúgy de, gotoval pont jól meg lehet csinálni az egyetlen kilépési pontot, ha éppen úgy az átláthatóbb.

--

Ha lehet, ne használj mallocot, mert olyankor van new meg scoped_ptr, unique_ptr.
----
India delenda est.
Hülye pelikán

Még mindig C programnál tartunk.

Nem, ott tartottunk, hogy mikor érdemes mallocot használni.
----
India delenda est.
Hülye pelikán

+sok. Vannak kollegák, akikkel szeretek dolgozni. Ők értik az RAII-t, a unique_ptr-t, a shared_ptr-t és társaikat.

Vannak olyanok, akik ezeket nem értik. Ők más utat követnek, mint én. Jobb, ha nem keresztezik egymást útjaink.

És még mindig C programnál tartunk. (De azért értékelem a próbálkozást;)

:)

Még mindig ott tartottunk, hogy ha LEHET akkor ne használj mallocot, és a legidálisabb eset amikor lehet nem használni az amikor C++-t használsz. Te - én: 1 - 0.
----
India delenda est.
Hülye pelikán

Ne áruld el senkinek, csak magunk közt mondom: a C++-ban pont az a jó, hogy abban mindentt lehet: egy olyan úniója egészen különböző koncepcióknak, hogy ahhoz képest a kacsa-sün-páva(*) egy teljesen normális állatfajta.

(*) Aki nem tudja, mi az, a szüleitől kérdezze meg.

És ez hol mond ellent nekem?
----
India delenda est.
Hülye pelikán

Őszintén szólva nem tudom. Most újra elolvastam az előző hozzászólásodat, és el kell ismerjem, hogy túl bonyolult nekem (ebben a központozás hiánya is szerepet játszhat) -- az előbb úgy értettem, hogy C++ nem lehet malloc-ot használni, de ez valószínűleg hibás értelmezés volt.

Valóban, a központozás nem lett tökéletes.
----
India delenda est.
Hülye pelikán

+1

Erre reagaltam: "(Ja, és a 'függvény közepéből return' dolgot hanyagoljuk, ronda gányolás)"

Egyebkent meg goto... egy C programban oke, de egy C++ programban pl. semmi keresnivaloja.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Fogalmam sincs a C++-ról, de ígéretes kezdeményezésnek tűnik, lehet hogy még lesz belőle valami... addig is maradok a C-nél.