1#include <stdlib.h>
2#include <stdio.h>
3#include "../../config.h"
4#if defined(HAVE_MALLINFO)
5#include <malloc.h>
6#endif
7
8#define BIGINCREASE 32000
9int debug = 0;
10
11void stats(char *msg)
12{
13#if defined(HAVE_MALLINFO)
14  struct mallinfo mallinfo_result;
15  mallinfo_result = mallinfo();
16#endif
17
18  /* from /usr/include/malloc.h */
19  printf("%s\n", msg);
20
21#if defined(HAVE_MALLINFO)
22  printf("%10d int arena;    /* non-mmapped space allocated from system */\n", mallinfo_result.arena);
23  printf("%10d int ordblks;  /* number of free chunks */\n", mallinfo_result.ordblks);
24  printf("%10d int smblks;   /* number of fastbin blocks */\n", mallinfo_result.smblks);
25  printf("%10d int hblks;    /* number of mmapped regions */\n", mallinfo_result.hblks);
26  printf("%10d int hblkhd;   /* space in mmapped regions */\n", mallinfo_result.hblkhd);
27  printf("%10d int usmblks;  /* maximum total allocated space */\n", mallinfo_result.usmblks);
28  printf("%10d int fsmblks;  /* space available in freed fastbin blocks */\n", mallinfo_result.fsmblks);
29  printf("%10d int uordblks; /* total allocated space */\n", mallinfo_result.uordblks);
30  printf("%10d int fordblks; /* total free space */\n", mallinfo_result.fordblks);
31  printf("%10d int keepcost; /* top-most, releasable (via malloc_trim) space */\n", mallinfo_result.keepcost);
32  printf("\n");
33#endif
34}
35
36int main(int argc, char *argv[])
37{
38
39  char *big = NULL;
40
41  char *newbig;
42  int malloc_failure = 0;
43  unsigned long bigsize = 8; // current size of the (reallocated) big block.
44  int i;
45  int loop;
46
47  // two optional arguments: [nr of loop] [debug]
48  if (argc > 1)
49     loop = atoi(argv[1]);
50  else
51     loop = 3000;
52
53  if (argc > 2)
54     debug = 1;
55
56  bigsize += BIGINCREASE;
57  big = malloc (bigsize);
58  if (big == NULL)
59     printf ("failure %d could not allocate size %lu\n",
60             ++malloc_failure, bigsize);
61  if (debug)
62     printf("big 0x%p\n", big);
63
64  for (i = 0; i < loop; i++)
65    {
66      bigsize += BIGINCREASE;
67      newbig = malloc(bigsize);
68      if (newbig == NULL)
69         printf ("failure %d could not allocate size %lu\n",
70                 ++malloc_failure, bigsize);
71      free (big);
72      big = newbig;
73      if (debug)
74         printf("big 0x%p\n", big);
75    }
76
77  printf ("after %d loops, last size block requested %lu\n", loop, bigsize);
78  // verify if superblock fragmentation occured
79  // We consider that an arena of up to 3 times more than bigsize is ok.
80  {
81#if defined(HAVE_MALLINFO)
82     struct mallinfo mallinfo_result;
83     mallinfo_result = mallinfo();
84     // Under valgrind, hblkhd is 0 : all the space is in arena.
85     // Under native linux, some space is counted hblkhd.
86     if (malloc_failure > 0)
87        printf ("%d mallocs failed, below output is doubful\n", malloc_failure);
88     if (mallinfo_result.arena + mallinfo_result.hblkhd > 3 * bigsize)
89        printf("unexpected heap fragmentation %lu\n",
90               (unsigned long) mallinfo_result.arena
91               + (unsigned long) mallinfo_result.hblkhd);
92     else
93#endif
94        printf("reasonable heap usage\n");
95  }
96
97  if (debug)
98     stats ("before freeing last block");
99  free (big);
100  if (debug)
101     stats ("after freeing last block");
102
103  return 0;
104}
105