Toon posts:

[c/c++] geheugen allocatie

Pagina: 1
Acties:
  • 278 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik ben al een tijdje in c/c++ bezig met een projectje en ik begin al steeds meer source te krijgen. Maar waar ik een beetje mee zit is het volgende.

Elke keer als ik een malloc uitvoer is er een kans dat het fout gaat, dus moet je altijd zoiets neerzetten als:
code:
1
2
if (!(var = malloc(size)))
  return ERROR;

Als ik een functie aanroep waar in ge-malloc-t word, word het weer zoiets:
code:
1
2
if (function() == ERROR)
  return ERROR;

Zo kan je door blijven gaan, als je veel functies hebt. Ik schrijf echter een hoop kleine hulp functies die nooit fout kunnen gaan, behalve door een malloc. Daardoor moet ik poepveel if'jes inbouwen en krijgt elke functie veel meer punten waarop ik errors kan verwachten.

Hou doen jullie dat, schrijven jullie ook een veel extra code om rekening te houden met een eventueel gebrek aan geheugen. Of gaan jullie er vanuit dat er genoeg geheugen is en dat een malloc altijd werkt.

PS: mijn code word er echt op veel punten twee keer zo groot van en veel minder overzichtelijk...

Verwijderd

lang leve de preprocessor!

#define SAFE_MALLOC(arg, size) if (((arg) = malloc(size)) == NULL) return ERROR

en gebruik in je source:
SAFE_MALLOC(schaap, 4 * sizeof(zoogdier));
oid :p

Maar let altijd op met #define's

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

ik doe altijd new, en die gooit een exception.

Die kun je evt afvangen als je dat wilt, maar als ie out of memory is dan heeft het toch weinig nut om door te gaan met je programma

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Dat is eventueel een mogelijheid, maar wat vooral een probleem is dat er meer gedaan moet worden.

voorbeeld functie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    err sysgroup_copy(sys_group *group, sys_group *&copy)
    {
     sys_node *cur, *tmp;
    if (!group)
      return 0;
1:    if (!sysgroup_init(copy, true))
      return 0;
    cur = group->first;
    while (cur)
    {
      if (!sysnode_copy(cur, tmp))
        goto error;
      if (!sysgroup_add(copy, tmp))
2:    goto error;
      cur =  cur->next;
    }
    return 1;
    error:
    sysgroup_kill(copy, true);
    return 0;
    }

bij 1 word er geheugen gealloceerd als dat goed gaat is dat heel mooi, maar op het moment dat het bij 2 fout gaat moet het bij 1 gealloceerde ook weer vrijgegeven worden. Deze functie is nog vrij simpel, maar geloof mij er zijn situaties dat dit redelijke complexiteit met zich mee brengt terwijl het anders zo kan:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    err sysgroup_copy(sys_group *group, sys_group *&copy)
    {
     sys_node *cur, *tmp;
    if (!group)
      return 0;
    sysgroup_init(copy, true);
    cur = group->first;
    while (cur)
    {
      sysnode_copy(cur, tmp);
      sysgroup_add(copy, tmp);
      cur =  cur->next;
    }
    return 1;
    }

dit is dezelfde functie, het enige verschil is dat er niet met eventuele allocatie-problemen rekening gehouden word...

know what i mean...

Verwijderd

Topicstarter
Op vrijdag 24 mei 2002 15:48 schreef .oisyn het volgende:
ik doe altijd new, en die gooit een exception.

Die kun je evt afvangen als je dat wilt, maar als ie out of memory is dan heeft het toch weinig nut om door te gaan met je programma
is idd een idee om geen errors te controleren en gewoon bij de eerste de beste alloc-failure er een exit(0) tegen aan te gooien. Het zou toch niet zo snel voorkomen, maar voor me gevoel schrijf ik dan crap code...

  • ^Mo^
  • Registratie: Januari 2001
  • Laatst online: 04-11 22:31
Op vrijdag 24 mei 2002 15:48 schreef .oisyn het volgende:
ik doe altijd new, en die gooit een exception.

Die kun je evt afvangen als je dat wilt, maar als ie out of memory is dan heeft het toch weinig nut om door te gaan met je programma
Erg afhankelijk van de compiler! Want new() in VC++ gooit geen exception maar returned gewoon NULL.

"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs


  • The End
  • Registratie: Maart 2000
  • Laatst online: 20:53

The End

!Beginning

Ik check het eigenlijk altijd wel, het heeft alleen niet echt zin... Als je programma geen geheugen meer krijgt, dan is het systeem zo vernaggeld, dat ze waarschijnlijk het crash dialoog niet meer te zien krijgen :)

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Op vrijdag 24 mei 2002 15:55 schreef _Mo_ het volgende:

Erg afhankelijk van de compiler! Want new() in VC++ gooit geen exception maar returned gewoon NULL.
en dan nu de MS quote
Beginning in Visual C++ .NET (version 7 of the compiler), the CRT's new function (in libc.lib, libcd.lib, libcmt.lib, libcmtd.lib, msvcrt.lib, and msvcrtd.lib) will continue to return NULL if memory allocation fails. However, the new function in the Standard C++ Library (in libcp.lib, libcpd.lib, libcpmt.lib, libcpmtd.lib, msvcprt.lib, and msvcprtd.lib) will support the behavior specified in the C++ standard, which is to throw a std::bad_alloc exception if the memory allocation fails.
I.e. de C Runtime library returned 0, maar in C++ krijg je dus inmiddels de exception.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
het programma wat ik aan het maken ben gaat ook met dynamische modules werken. Nu wil ik niet dat als een van de modules op het idee komt ff 1400 MB te alloceren dat mijn core er maar mee nokt omdat er een exit(..) gegenereerd wordt..

Verwijderd

the end:
tenzij je een malloc van een paar honderd meg doet ;) dan hoeft 't nog niet superveel te betekenen als 't mislukt

Verwijderd

IIRC is exception bende pas gedefinieerd in C++ handel, en is setjmp/longjmp de exception voorganger in C.

Maar wat betreft exceptions in C++, hangt het er vanaf per compiler hoe goed het ondersteund wordt, en of het niet compleet genegeerd wordt. Compilerafhankelijkheid kan een opoffering zijn.

Met een beetje logisch inzicht kan je er toch dit van maken?
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
err sysgroup_copy(sys_group *group, sys_group *&copy)
    {
     sys_node *cur, *tmp;
    if (!group || 
        !sysgroup_init(copy, true))
      return 0;

    cur = group->first;
    while (cur)
    {
      if (!sysnode_copy(cur, tmp) ||
        !sysgroup_add(copy, tmp)) {
        sysgroup_kill(copy, true);
        return 0;
      }
      cur =  cur->next;
    }
    return 1;
    }

en da's een pietsie leesbaarder. arguably. ;)

Owja. Mallocs 'zou je eigenlijk altijd moeten checken'. Als door een programmeerfout ergens een paar ((unsigned int) -1) bytes worden gealloceerd, wil je daar liever een ENOMEM error van terugkrijgen dan een vage nullpointer error of een bsod/segfault.

Verwijderd

Topicstarter
ik vind 'm niet echt leesbaarder, maar da's vast een kwestie van smaak.. (en mijn voorbeeld zou onduidelijker zijn)

maar ik heb nu een nieuw ideetje.
Alle allocaties gaan bij mij via een eigen functie zodat ik het kan loggen e.d. Maar nu defineer ik een kritieke groote (bv 8192 bytes), die altijd alloceerbaar moet zijn. Is dat niet het geval, dan is er ECHT iets mis en gaat de alloc-functie over in een while (1);. Lukt het niet maar word er meer aangevraagd dan die limiet dan returned mijn alloc functie gewoon een error, maar gaat het programma gewoon door, zodat alle acties met kleine structures enzo geen extra controle vereisen...

edit:
dit heeft ook weer z'n nadelen bedenk ik me net

Verwijderd

Op vrijdag 24 mei 2002 15:53 schreef unteraarsch het volgende:
is idd een idee om geen errors te controleren en gewoon bij de eerste de beste alloc-failure er een exit(0) tegen aan te gooien. Het zou toch niet zo snel voorkomen, maar voor me gevoel schrijf ik dan crap code...
Het kan nog iets makkelijker. Ideetje uit de xawtv source, gewoon een define maken die de line, een standaard error etc. uitprint:
code:
1
2
3
4
5
6
7
8
9
#define ALLOC_EXIT() \
  do \
  { \
    fprintf(stderr, \
    "Error trying to allocate memory at file '%s', line %d: %s\n", \
    __FILE__, __LINE__, sys_errlist[errno]); \
    exit(1); \
  } \
  while (0);

(de do { .. } while (0); eromheen is cosmetisch, dat gebruik ik voor ingewikkelder macro's die eigen variabelen etc. nodig hebben. Gewoon { .. } wordt niet door elke compiler geaccepteerd, do { .. } while (0); wel.

Geen crap-code (behalve de macro zelf) en toch alle informatie. :Y).

Verwijderd

Op vrijdag 24 mei 2002 16:01 schreef The End het volgende:
Ik check het eigenlijk altijd wel, het heeft alleen niet echt zin... Als je programma geen geheugen meer krijgt, dan is het systeem zo vernaggeld, dat ze waarschijnlijk het crash dialoog niet meer te zien krijgen :)
Dat ligt dan aan de andere applicaties en het systeem zelf. Een goed systeem cleant up als er geen mem meer is, en blijft dan dus draaien.

M.a.w., het feit dat de rest brak is betekent niet dat je je eigen spul ook wel brak kunt maken. Da's de omgekeerde wereld.

Verwijderd

Topicstarter
Op vrijdag 24 mei 2002 16:50 schreef beelzebubu het volgende:
Geen crap-code (behalve de macro zelf) en toch alle informatie. :Y).
uhh.. dit kan toch ook met een functie ipv macro..
lijkt mij iets netter...

Verwijderd

Op vrijdag 24 mei 2002 17:29 schreef unteraarsch het volgende:

[..]

uhh.. dit kan toch ook met een functie ipv macro..
lijkt mij iets netter...
Nee.

__FILE__ en __LINE__. ;).

  • whoami
  • Registratie: December 2000
  • Laatst online: 21:13
Op vrijdag 24 mei 2002 15:53 schreef unteraarsch het volgende:

is idd een idee om geen errors te controleren en gewoon bij de eerste de beste alloc-failure er een exit(0) tegen aan te gooien. Het zou toch niet zo snel voorkomen, maar voor me gevoel schrijf ik dan crap code...
Een exit(0) als er iets verkeerd gegaan is? Als er iets mis gaat en je wilt het programma afsluiten doe je dan toch een exit(-1) of exit(1) ofzo.

https://fgheysels.github.io/


  • The End
  • Registratie: Maart 2000
  • Laatst online: 20:53

The End

!Beginning

Op vrijdag 24 mei 2002 16:56 schreef beelzebubu het volgende:

[..]

Dat ligt dan aan de andere applicaties en het systeem zelf. Een goed systeem cleant up als er geen mem meer is, en blijft dan dus draaien.

M.a.w., het feit dat de rest brak is betekent niet dat je je eigen spul ook wel brak kunt maken. Da's de omgekeerde wereld.
Dat klopt en daar ben ik het ook mee eens (er stond ook bij dat ik het zelf altijd wel check) Maar er stond ook een smiley achter.... :P

Verwijderd

Op vrijdag 24 mei 2002 18:56 schreef whoami het volgende:

[..]

Een exit(0) als er iets verkeerd gegaan is? Als er iets mis gaat en je wilt het programma afsluiten doe je dan toch een exit(-1) of exit(1) ofzo.
Mjah, da's de conventie. Maar voor 90% van de applicaties wordt de return code toch nooit gecontroleerd en maakt het dus geen reet uit. :P. Alleen voor console helper progjes kan het wat uitmaken...

bv:
code:
1
2
3
4
(./configure && \
  make && \
  make install ) || \
echo "Whoops - your computer sucks"

Dan wordt de error code gebruikt. Maar voor de meeste apps wordt die nooit gebruikt en maakt het dus niks uit.

  • windancer
  • Registratie: Maart 2000
  • Laatst online: 30-11 18:23
Je kunt ook met assert's werken :
code:
1
2
p = malloc (whatever);
assert (p != NULL);

of zelfs
code:
1
2
p = malloc (whatever);
assert (p);

je hebt dat je hele foutafhandeling in 1 regeltje. Nadeel is wel dat je hele applicatie onderuit gaat als het een keertje fout gaat.

  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 06-12 23:40

Aaargh!

Bow for me for I am prutser

Is het gebruik van malloc niet iets wat je wilt voorkomen in C++ ?

Those who do not understand Unix are condemned to reinvent it, poorly.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

of zelfs
code:
1
assert (p = malloc (whatever));

;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 07-12 20:56
Op vrijdag 24 mei 2002 22:16 schreef windancer het volgende:
Je kunt ook met assert's werken :
Wel aardig in een debug build om een assertion error te krijgen, maar dat is geen foutafhandeling natuurlijk.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

Topicstarter
Op vrijdag 24 mei 2002 23:27 schreef Aaargh! het volgende:
Is het gebruik van malloc niet iets wat je wilt voorkomen in C++ ?
ik niet, ik vind malloc uiterst handig, maar mijn met de C++ gecompileerde programma's zijn ook meer C. Ik gebruik geen klasses en al dat soort meuk.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21:13
Op zaterdag 25 mei 2002 10:23 schreef unteraarsch het volgende:

[..]

ik niet, ik vind malloc uiterst handig, maar mijn met de C++ gecompileerde programma's zijn ook meer C. Ik gebruik geen klasses en al dat soort meuk.
Waarom niet?

https://fgheysels.github.io/


Verwijderd

Topicstarter
laten we die discussie maar niet begginnen...
en anders in een andere topic...

  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 06-12 23:40

Aaargh!

Bow for me for I am prutser

Op zaterdag 25 mei 2002 10:23 schreef unteraarsch het volgende:
ik niet, ik vind malloc uiterst handig, maar mijn met de C++ gecompileerde programma's zijn ook meer C. Ik gebruik geen klasses en al dat soort meuk.
Maar dan jaag je een C programma door een C++ compiler. maar als je echt netjes OO wilt proggen in C++ dan zal je liever geen malloc willen gebruiken.

Those who do not understand Unix are condemned to reinvent it, poorly.


Verwijderd

Topicstarter
het is idd meer C dan C++, maar om nou te zeggen dat ik alles wat ik programmeer helemaal volgens Ansi standaard is, nee niet echt.

Maar om even on-topic te blijven, over alloceren.
Het vervelende aan new/delete ten opzichte van malloc/free is. Dat je om malloc en free makkelijk een eigen functie heen kan schrijven, die ook nog eens logt hoeveel er gealloceerd en vrijgegeven word. Zodat je goed op de hoogte bent van memory leaks. Dit kan met new en delete vast ook wel, maar dan moet de preprocessor weer in het spel komen. En dan vind ik new/delete echt niet zo handig meer.

  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 06-12 23:40

Aaargh!

Bow for me for I am prutser

Je kan new en delete gewoon overloaden iirc, op die manier kan b.v. garbage collection worden geimplementeerd in C++

Those who do not understand Unix are condemned to reinvent it, poorly.

Pagina: 1