[win32|c++] realloc om memory te shrinken

Pagina: 1
Acties:

  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
Hoi,

Volgens den docs zou het mogelijk moeten zijn om met realloc ook te realloc'en naar een kleiner stuk geheugen.

Als ik dit test wordt er echter geen geheugen vrijgegeven.

code:
1
2
3
4
5
6
7
8
   size_t size = 0;
   void* p = malloc( sizeof(byte) * 1024*1024*1500 );
   size = _msize( p );

   p = realloc( p, 1 );
   size = _msize( p );

   void* p2 = malloc( sizeof(byte) * 1024*1024*750 );

de 2e malloc mislukt, terwijl _msize wel de 'gereallocte' grootte teruggeeft.

Weet iemand waarom dat zo is ?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Beetje vreemd dat dat niet zou werken, maar doe eens een _heapmin() na de realloc?

Professionele website nodig?


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
die had ik ook al geprobeerd... geen effect helaas

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

demonite schreef op 01 juni 2004 @ 08:41:
die had ik ook al geprobeerd... geen effect helaas
En is er verschil tussen release en debugbuild of gaat het in beiden fout? En werkt het wel als je de realloc vervangt door een free?

[edit]

Even getest, en bij mij (VS.net 2003 op WinXP SP1) werkt je code naar behoren. Oftewel de eerste alloc lukt, geeft spike tot bijna top in taskmanager, zakt terug naar originele niveau bij realloc, en geeft halve originele spike bij 2e alloc. Zonder _heapmin tussendoor dus.... :?

[ Voor 35% gewijzigd door curry684 op 01-06-2004 08:54 ]

Professionele website nodig?


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
gaat fout in release en debug..

realloc(p, 0) werkt wel ( in feit een free() ).
gewoon free( p ) werkt ook...

maarja, dat is net ietsje teveel weggooien.

er is ook nog een _expand() maar die gedraagt zich net zoals de realloc()

  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
Ik heb vs c++ 6.0 met intel 7.1 compilers (ook met msvc compiler gaat het mis btw).. windows xp ook met sp1

vreemde zaak...

  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

Van Linux weet ik dat ie nooit meer geheugen vrij geeft aan het OS als een app geheugen vrij geeft. Waarschijnlijk is dat in Windows ook zo. Je kan freeen wat je wilt, maar dat geheugen blijft voor je app gereserveerd. Pas als de app afsluit wordt het geheugen vrij gegeven.

"Beauty is the ultimate defence against complexity." David Gelernter


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:19
Macros: dat kan best kloppen, maar dat geldt dan alleen voor de bij het besturingssystem gealloceerde pages. Die pages worden door de standaard C library gebruikt om geheugen 'op maat' te leveren aan C applicaties via functies als malloc(), free(), enzovoorts. De C library zal zeker met free() vrijgegeven geheugen weer beschikbaar maken voor latere allocaties met alloc(); gedurende de looptijd van een applicatie worden er immers heel veel objecten tijdelijk aangemaakt en al snel weer verwijderd. Het zou onmogelijk worden om een langdurig proces als een daemon te schrijven als er alleen maar meer geheugen gealloceerd zou worden.

Hoe dan ook lijkt Windows toch echt heel anders te werken, wat uit het experiment van curry684 blijkt. Misschien ligt het aan de standaard C library van Visual Studio 6? Welke standaard C library gebruikt die Intel compiler; pakt 'ie die van Visual Studio of hebben ze een eigen versie? In het eerste geval is het natuurlijk wel logisch dat het gedrag hetzelfde is.

  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
Het vreemde is, dat op een andere pc dit programmaatje wel werkt... Terwijl ie singlethreaded gelinkt is (statisch c runtime meegelinkt).

Ik heb 'm ook nog gelinkt met een multithreaded DLL c runtime.. Vervolgens een msvcr71.dll gerenamed naar msvcrt.dll... (ja dat werkt wonderbaarlijk) Maar ook dat levert geen verschil op...

Blijkbaar ligt het niet aan de C runtime...

De twee dependencies van de C runtime zijn kernel32.dll en ntdll.dll maar die zijn wat lastig te vervangen aangezien het "known" dll's zijn.. Eens rebooten, kijken of dat helpt

edit:
Helaas...

[ Voor 5% gewijzigd door demonite op 01-06-2004 10:49 ]


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

demonite schreef op 01 juni 2004 @ 08:19:
code:
1
2
3
4
5
6
7
8
   size_t size = 0;
   void* p = malloc( sizeof(byte) * 1024*1024*1500 );
   size = _msize( p );

   p = realloc( p, 1 );
   size = _msize( p );

   void* p2 = malloc( sizeof(byte) * 1024*1024*750 );

Weet iemand waarom dat zo is ?
realloc() kan mis gaan, net zoals elke call. Het is implementatieafhankelijk of je van 1.5 GB terug kan gaan naar 1 byte, en aangezien d'r geen OS is dat 1.5 GB op de heap zet wordt d'r een mmap() variant gebruikt.

Ik zou even een check doen op de return waarde. Verder : Op welke Windows versie draai je dit ? D'r zijn diverse problemen met de heap implementatie onder Win '95 / 98 / ME, en ook diverse problemen met de VS implementatie (die afaik allen zijn opgelost in servicepacks).

Results :

Ik moest 1500 vervangen door 250, anders doet malloc() het helemaal niet hier. Verder werkt de code zoals vewacht : 250 meg alloceren, vrijgeven, weer 250 meg alloceren. De taskmanager laat 2 pieken zien.

VS 6.0 zonder SP (of anders met 1 SP), Windows 2k SP4.

[ Voor 24% gewijzigd door igmar op 01-06-2004 12:34 ]


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
Windows XP sp1
Visual Studio 6.0 SP 5
Intel 7.1 c++ compilers

Release en debug gaan fout.. Maar met de debugger kan ik alle waardes checken.
Alles gaat zoals het hoort (ook de _msize() calls), maar de 2e malloc mislukt (geeft null pointer terug) terwijl ik verwacht dat de realloc de 1.5 GB weer vrijgeeft (op 1 byte na)

Als ik dit programma op een flop zet en wat andere pc's uitprobeer gaat het bij de ene wel goed en bij de andere weer niet...

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

demonite schreef op 01 juni 2004 @ 11:43:
Windows XP sp1
Visual Studio 6.0 SP 5
Intel 7.1 c++ compilers

Release en debug gaan fout.. Maar met de debugger kan ik alle waardes checken.
Alles gaat zoals het hoort (ook de _msize() calls), maar de 2e malloc mislukt (geeft null pointer terug) terwijl ik verwacht dat de realloc de 1.5 GB weer vrijgeeft (op 1 byte na)
Maar wat toont task manager terwijl je er doorheen stept? :?

Professionele website nodig?


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
Dat is raar..

Volgens de taskmanager doet de realloc( p,1) wel z'n werk.


Ik heb een example van Jeffrey Richter uit Programming Applications for Windows overgenomen en aangepast waarmee je door het virtual memory van een app kan wandelen.. Volgens deze tool is het geheugen ook nog in gebruik. Itt wat taskmanager zegt. :?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Er is overigens een SP6 voor VS6 he

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

demonite schreef op 01 juni 2004 @ 11:43:
Als ik dit programma op een flop zet en wat andere pc's uitprobeer gaat het bij de ene wel goed en bij de andere weer niet...
Gokje: in die systemen waar het fout gaat zit weinig geheugen en kan windows om e.o.a. reden geen swapfile van pakweg 2,5 GB maken/gebruiken?

[ Voor 3% gewijzigd door Verwijderd op 01-06-2004 18:01 ]


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
nope.. ik heb 3 GB in mijn pc zitten maar het helpt niet.. Daarbij, als je bijna door je maximum memory heen gaat krijg je meestal een melding van windows ("low on memory" oid)

Ik ga zo eens wat win2k machines testen, kijken of die het beter doen..

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

demonite schreef op 02 juni 2004 @ 08:01:
nope.. ik heb 3 GB in mijn pc zitten maar het helpt niet.. Daarbij, als je bijna door je maximum memory heen gaat krijg je meestal een melding van windows ("low on memory" oid)

Ik ga zo eens wat win2k machines testen, kijken of die het beter doen..
Wat je even moet doen is een memset() om het gealloceerde geheugen te vullen met nullen (of een andere waarde). Zowat alle *NIX OS'ses gaan pas daadwerkelijk pages alloceren zodra er in geschreven wordt.

Ikzelf kan op deze win2k bak niet meer dan 300 meg malloc'en, daarboven geeft malloc NULL terug. Verder is de splitsing van je address space ook nog van invloed : Vaak is die 1:3 of 2:2 (kernelspace : userspace).

  • drZymo
  • Registratie: Augustus 2000
  • Laatst online: 12-04 13:01
Moet het ook een Win32 applicatie blijven? Zo ja, dan kan je mischien proberen de native Win32 API functies voor geheugen beheer te gebruiken. Zoals HeapAlloc() en HeapRealloc() met GetProcessHeap() als heap.

En aangezien het om nogal veel geheugen gaat, mischien zijn de VLM (Very Large Memory) API functies wel handiger om te gebruiken.

[ Voor 3% gewijzigd door drZymo op 02-06-2004 09:37 ]

"There are three stages in scientific discovery: first, people deny that it is true; then they deny that it is important; finally they credit the wrong person."


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Om heel eerlijk te zijn: Het is C++, geen C, dus waarom geen std::deque gebruiken? Die kan veel makkelijker boven de 1G komen.

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


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

MSalters schreef op 02 juni 2004 @ 10:22:
Om heel eerlijk te zijn: Het is C++, geen C, dus waarom geen std::deque gebruiken? Die kan veel makkelijker boven de 1G komen.
Ik geloof niet echt dat die app uit de topicstart een productie-applicatie is, oftewel het gaat volgens mij meer om het analyseren van dit vreemde gedrag dan om een vervangende oplossing voor dit geisoleerde probleem ;)

Professionele website nodig?


Verwijderd

demonite schreef op 02 juni 2004 @ 08:01:
nope.. ik heb 3 GB in mijn pc zitten maar het helpt niet.. Daarbij, als je bijna door je maximum memory heen gaat krijg je meestal een melding van windows ("low on memory" oid)
3 GB hebben wil niet zeggen dat er ook 3 GB beschikbaar zijn als heap. Wat gebeurt er als je in incrementele stapjes probeert te mallocen; bij welke stap gaat het fout?

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <stdlib.h>

const size_t MEGA= 1024 * 1024 * sizeof(char);

int main(int argc, char *argv[])
{
    void *p1, *p2, *p3;
    size_t space= argc == 2 ? atoi(argv[1]) : 1;
    for(;;) {
        p1= malloc(2 * space * MEGA);
        if(!p1) {
            printf("malloc(%u MB) == NULL\n", 2 * space);
            break;
        }
        p2= realloc(p1, 1);
        if(!p2) {
            printf("realloc(%u MB -> 1 B) == NULL\n", 2 * space);
            free(p1);
            break;
        }
        p3= malloc(space * MEGA);
        if(!p3) {
            printf("realloc(%u MB -> 1 B) & malloc(%u MB) == NULL\n",
                    2 * space, space);
            free(p2);
            break;
        }
        free(p2);
        free(p3);
        space*= 2;
    }
    return EXIT_SUCCESS;
}


Als je een dergelijk experimenteel programmaatje eens laat lopen, met welke melding komt het dan?

[ Voor 4% gewijzigd door Verwijderd op 02-06-2004 17:57 ]


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
malloc(2048 MB) == NULL


Dit klopt, maar dat is logisch want alles wordt gefreed aan het einde van de loop.
Als ik het nog een keer doe, maar nu p2 niet free. Dan krijg ik dit:

malloc(1024 MB) == NULL


p1 is ge-realloced naar 1 byte (p2). Dus op dat moment heb ik 10 byte aan p2's nog in het geheugen zitten.... Maar dat is dus niet het geval!

Als ik door het virtual memory heen wandel zie ik dat er 1 GB nog steeds gealloceerd is. Volgens taskmanager is de mem usage maar 64 k.

Zelfs al zou het wel vrijgegeven worden zou het nog niet werken realiseer ik me nu... Want die 10 byte staat verspreid door het geheugen waardoor er geen 1 GB memblock meer is...


Heb je de code van mijn programmatje al eens geprobeerd ?

Deze versie kan dan zonder debugger:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int main(int argc, char *argv[]) 
{ 
   // allocate 1.5 GB
   void * p1 = malloc( sizeof(char) * 1024 * 1024 * 1500 );

   if( !p1 )
   {
      printf( "failed to allocate 1.5GB\n" );
      return 0;
   }

   // free 1.5 GB except 1 byte
   void* p2 = realloc( p1, 1 );

   if( !p2 )
   {
      printf( "realloc failed\n" );
      return 0;
   }

   // allocate 500 MB
   void* p3 = malloc( sizeof(char) * 1024 * 1024 * 500 );

   if( !p3 )
   {
      printf( "malloc 500 MB failed\n" );
   }
   else
   {
      printf( "success!\n" );
   }


   return 0;
}


en idd, mij gaat het erom waarom op een aantal pc's de malloc 500 meg mislukt.
Dat kan alleen maar als realloc geen geheugen vrij heeft gegeven en dat is niet zoals het behoort te werken.

[ Voor 9% gewijzigd door demonite op 03-06-2004 08:18 ]


  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
igmar schreef op 02 juni 2004 @ 08:55:
[...]
Ikzelf kan op deze win2k bak niet meer dan 300 meg malloc'en, daarboven geeft malloc NULL terug. Verder is de splitsing van je address space ook nog van invloed : Vaak is die 1:3 of 2:2 (kernelspace : userspace).
300 meg ? is dat niet wat weinig ? Elke proces heeft 2 GB aan virtual memory ter beschikking (of je nou 32 mb ram of 2 gb ram hebt), tenzij je idd boot met /3GB optie.

Als een malloc van 300 meg mislukt heb je 2 mogelijkheden:
1) je virtual memory is gefragmenteerd door DLL's (zoals uxtheme.dll)
2) je swapfile setting is te klein, maar meestal krijg je dan een melding van windows hierover.

Verwijderd

demonite schreef op 03 juni 2004 @ 08:12:
p1 is ge-realloced naar 1 byte (p2). Dus op dat moment heb ik 10 byte aan p2's nog in het geheugen zitten.... Maar dat is dus niet het geval!

Als ik door het virtual memory heen wandel zie ik dat er 1 GB nog steeds gealloceerd is. Volgens taskmanager is de mem usage maar 64 k.
Wat zegt _heapchk() (ik kan dit niet zelf uitproberen, ik heb geen windows-machines in huis)?
C:
27
      if(_heapchk() != _HEAPOK) puts("Heap smashed!");

in je code zetten (en malloc.h includen).

  • demonite
  • Registratie: April 2000
  • Laatst online: 23-05 06:25

demonite

the way is up

Topicstarter
Ik ben er achter wat er aan de hand is.

malloc alloceert een berg pages, die krijgen de status MEM_COMMIT.

realloc houdt de pages die nodig zijn vast (is maar 1 page, voor die ene byte) en de rest krijgt de status MEM_RESERVED

wat wil zeggen dat de ruimte in het virtual memory "gereserveerd" is, maar er is geen daadwerkelijke 'storage' voor.

Het probleem is het volgende:
MEM_RESERVE
Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.
Other memory allocation functions such as malloc and LocalAlloc, cannot use a reserved range of memory until it is released.

You can commit reserved memory pages in subsequent calls to the VirtualAlloc function.


daarom mislukt de malloc dus!


waarom realloc (blijkbaar) verschillend werkt op andere machines is me nog steeds een raadsel...

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Hulde voor het posten van deze uitleg, dat doen helaas te weinig mensen d:)b

Professionele website nodig?

Pagina: 1