LINUX.ORG.RU

STL и аллокация памяти, Linux 2.4.22, g++ 3.2.2


0

0

Проблеммный код:

#include <string.h> #include <string> #include <vector>

int main () { MEM_DEBUG_ON;

{ char test[1024]; memset (test, 'a', 1023); test[1023]=0; std::vector<std::string> vec; for (int i=0; i<10; i++) { std::string s1(test); vec.push_back(s1); }

vec.clear(); }

MEM_DEBUG_OFF;

return 0; }

Код дебаггера памяти:

#include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <fcntl.h>

#define MAX_MALLOCS 10000 #define RES_FILE "./mem_allocs_stat"

/* Prototypes for our hooks. */ static void my_init_hook(void); static void *my_malloc_hook(size_t, const void *); static void my_free_hook(void *ptr, const void *caller);

static unsigned long mem_count; static unsigned int addr_hash[MAX_MALLOCS][2]; static unsigned int hash_number; FILE * f; /* Variables to save original hooks. */ static void *(*old_malloc_hook)(size_t, const void *); static void (*old_free_hook)(void *ptr, const void *caller);

/* Override initialising hook from the C library. */ void (*__malloc_initialize_hook) (void) = my_init_hook; static void * my_malloc_hook (size_t size, const void *caller) { void *result; __malloc_hook = old_malloc_hook; result = malloc (size);

int i; for (i=0; i<MAX_MALLOCS; i++) { if ( !addr_hash[i][0] ) { addr_hash[i][0] = (unsigned)result; addr_hash[i][1] = size; break; } } if (i<MAX_MALLOCS) hash_number++; else fprintf (f, "WARNING: too much mallocs\n"); old_malloc_hook = __malloc_hook; fprintf (f, "malloc(%u) called from %p returns %p0\n", (unsigned int) size, caller, result); __malloc_hook = my_malloc_hook; return result; }

static void my_free_hook (void *ptr, const void *caller) { __free_hook = old_free_hook; free(ptr);

int i; for (i=0; i<hash_number; i++) { if (addr_hash[i][0] == (unsigned)ptr) { addr_hash[i][0] = 0; } } if (i==hash_number-1) hash_number--;

old_free_hook = __free_hook; fprintf (f, "free(%p0) called form %p\n", ptr, caller); __free_hook = my_free_hook; }

static void print_result () { for (int i=0; i<hash_number; i++) if ( addr_hash[i][0] ) { fprintf (f, "\t0x%x %d bytes\n", addr_hash[i][0], addr_hash[i][1]); mem_count += addr_hash[i][1]; } fprintf (f, "memory allocation result: %u\n", mem_count);

fclose (f); }

#define MEM_DEBUG_ON mem_debug_activate()

#define MEM_DEBUG_OFF \ __malloc_hook = old_malloc_hook; \ __free_hook = old_free_hook

static void mem_debug_activate () { #ifdef DEBUG f = fopen(RES_FILE, "w+");

if ( !!atexit(print_result) ) exit(-1);

old_malloc_hook = __malloc_hook; __malloc_hook = my_malloc_hook;

old_free_hook = __free_hook; __free_hook = my_free_hook;

#endif }

Собственно просто смотрим выделение памяти.

Вывод дебаггера

[lunc@kain temp]$ cat mem_allocs_stat 0 malloc(1136) called from 0x400b2e9e returns 0x805efe80 // выделение памяти для строки 1 malloc(320) called from 0x400b2e9e returns 0x805f4600 // ???? 2 malloc(1136) called from 0x400b2e9e returns 0x805f5a80 3 malloc(1136) called from 0x400b2e9e returns 0x805fa200 4 malloc(1136) called from 0x400b2e9e returns 0x805fe980 5 malloc(1136) called from 0x400b2e9e returns 0x80603100 6 malloc(1304) called from 0x400b2e9e returns 0x80607880 // ???? 7 malloc(1136) called from 0x400b2e9e returns 0x8060ca80 8 malloc(1136) called from 0x400b2e9e returns 0x80611200 9 malloc(1136) called from 0x400b2e9e returns 0x80615980 10 malloc(1136) called from 0x400b2e9e returns 0x8061a100 11 malloc(1136) called from 0x400b2e9e returns 0x8061e880 free(0x805efe80) called form 0x400b1983 free(0x805f5a80) called form 0x400b1983 free(0x805fa200) called form 0x400b1983 free(0x805fe980) called form 0x400b1983 free(0x80603100) called form 0x400b1983 free(0x8060ca80) called form 0x400b1983 free(0x80611200) called form 0x400b1983 free(0x80615980) called form 0x400b1983 free(0x8061a100) called form 0x400b1983 free(0x8061e880) called form 0x400b1983

Итого потреянно 1624 байта. Если сделать около 100 итреаций получится порядка 7Kb (добавляется еще одна аллокация, которая потом не освобождается). Такое поведение возникает только при использовании push_back() (если создать вектор заранее с заданным размером, а потом пихать в него элементы -- память освободится полностью). С list та же история -- только аллокации другие.

Может быть я не правильно хуки поставил. Использовал mtrace: Цитата

@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805f0b0 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805f528 0x140 // 320 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805f670 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805fae8 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805ff60 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x80603d8 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8060850 0x518 // 1304 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8060d70 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x80611e8 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8061660 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8061ad8 0x470 @ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8061f50 0x470 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805f0b0 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805f670 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805fae8 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805ff60 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x80603d8 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8060d70 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x80611e8 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8061660 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8061ad8 @ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8061f50

Та же самая память...

В чем дело?


Прошу прощения. Попробую отфрматировать...

 Проблеммный код:

#include <string.h>
#include <string>
#include <vector>

int
main ()
{
  MEM_DEBUG_ON;

  {
    char test[1024];
    memset (test, 'a', 1023);
    test[1023]=0;
    
    std::vector<std::string> vec;
    
    for (int i=0; i<10; i++) {
      std::string s1(test);
      vec.push_back(s1);
    } 

    vec.clear();
  }

  MEM_DEBUG_OFF;

  return 0;
}


Код дебаггера памяти:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <fcntl.h>

#define MAX_MALLOCS 10000
#define RES_FILE "./mem_allocs_stat"


/* Prototypes for our hooks.  */
static void my_init_hook(void);
static void *my_malloc_hook(size_t, const void *);
static void my_free_hook(void *ptr, const void *caller);

static unsigned long mem_count;
static unsigned int addr_hash[MAX_MALLOCS][2];
static unsigned int hash_number;
FILE * f;
 
/* Variables to save original hooks. */
static void *(*old_malloc_hook)(size_t, const void *);
static void (*old_free_hook)(void *ptr, const void *caller);

/* Override initialising hook from the C library. */
void (*__malloc_initialize_hook) (void) = my_init_hook;
                                                                                      
static void *
my_malloc_hook (size_t size, const void *caller) {
  void *result;
  
  __malloc_hook = old_malloc_hook;
  
  result = malloc (size);

  int i;
  for (i=0; i<MAX_MALLOCS; i++) {
    if ( !addr_hash[i][0] ) {
      addr_hash[i][0] = (unsigned)result;
      addr_hash[i][1] = size;
      break;
    }
  }
  if (i<MAX_MALLOCS)
    hash_number++;
  else
    fprintf (f, "WARNING: too much mallocs\n");
  
  old_malloc_hook = __malloc_hook;
  
  fprintf (f, "malloc(%u) called from %p returns %p0\n",
        (unsigned int) size, caller, result);
  
  __malloc_hook = my_malloc_hook;
  
  return result;
}


static void
my_free_hook (void *ptr, const void *caller)
{
  __free_hook = old_free_hook;
  free(ptr);

  int i;
  for (i=0; i<hash_number; i++) {
    if (addr_hash[i][0] == (unsigned)ptr) {
      addr_hash[i][0] = 0;
    }
  }
  if (i==hash_number-1)
    hash_number--;

  old_free_hook = __free_hook;
  fprintf (f, "free(%p0) called form %p\n", ptr, caller);
  __free_hook = my_free_hook;
}


static void
print_result ()
{
  for (int i=0; i<hash_number; i++)
    if ( addr_hash[i][0] ) {
      fprintf (f, "\t0x%x %d bytes\n", addr_hash[i][0], addr_hash[i][1]);
      mem_count += addr_hash[i][1];
    }
  fprintf (f, "memory allocation result: %u\n", mem_count);

  fclose (f);
}


#define MEM_DEBUG_ON mem_debug_activate()

#define MEM_DEBUG_OFF \
  __malloc_hook = old_malloc_hook; \
  __free_hook = old_free_hook


static void
mem_debug_activate ()
{
#ifdef DEBUG
  f = fopen(RES_FILE, "w+");

  if ( !!atexit(print_result) )
    exit(-1);

  old_malloc_hook = __malloc_hook;
  __malloc_hook = my_malloc_hook;

  old_free_hook = __free_hook;
  __free_hook = my_free_hook;

#endif
}

Собственно просто смотрим выделение памяти.

Вывод дебаггера


[lunc@kain temp]$ cat mem_allocs_stat
0 malloc(1136) called from 0x400b2e9e returns 0x805efe80    // выделение памяти для строки
1 malloc(320) called from 0x400b2e9e returns 0x805f4600    // ????
2 malloc(1136) called from 0x400b2e9e returns 0x805f5a80
3 malloc(1136) called from 0x400b2e9e returns 0x805fa200
4 malloc(1136) called from 0x400b2e9e returns 0x805fe980
5 malloc(1136) called from 0x400b2e9e returns 0x80603100
6 malloc(1304) called from 0x400b2e9e returns 0x80607880  // ????
7 malloc(1136) called from 0x400b2e9e returns 0x8060ca80
8 malloc(1136) called from 0x400b2e9e returns 0x80611200
9 malloc(1136) called from 0x400b2e9e returns 0x80615980
10 malloc(1136) called from 0x400b2e9e returns 0x8061a100
11 malloc(1136) called from 0x400b2e9e returns 0x8061e880
free(0x805efe80) called form 0x400b1983
free(0x805f5a80) called form 0x400b1983
free(0x805fa200) called form 0x400b1983
free(0x805fe980) called form 0x400b1983
free(0x80603100) called form 0x400b1983
free(0x8060ca80) called form 0x400b1983
free(0x80611200) called form 0x400b1983
free(0x80615980) called form 0x400b1983
free(0x8061a100) called form 0x400b1983
free(0x8061e880) called form 0x400b1983

Итого потреянно 1624 байта. Если сделать около 100 итреаций получится порядка 7Kb (добавляется еще одна аллокация, которая потом не освобождается).
Такое поведение возникает только при использовании push_back() (если создать вектор заранее с заданным размером, а потом пихать в него элементы -- память освободится полностью). С list та же история -- только аллокации другие.

Может быть я не правильно хуки поставил. Использовал mtrace:
Цитата

@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805f0b0 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805f528 0x140  // 320
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805f670 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805fae8 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x805ff60 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x80603d8 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8060850 0x518  // 1304
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8060d70 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x80611e8 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8061660 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8061ad8 0x470
@ /usr/lib/libstdc++.so.5:(_Znwj+0x2e)[0x400b2e9e] + 0x8061f50 0x470
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805f0b0
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805f670
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805fae8
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x805ff60
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x80603d8
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8060d70
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x80611e8
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8061660
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8061ad8
@ /usr/lib/libstdc++.so.5:(_ZdlPv+0x23)[0x400b1983] - 0x8061f50

Таже самая память...

В чем дело?

lunc
() автор топика
Ответ на: комментарий от anonymous

> дело (кто бы сомневался) естественно в кривых руках

Зашибись ответ. Может быть поясните?

lunc
() автор топика
Ответ на: комментарий от lunc

Ну зачем ему объяснять, сам подумай. Обосрал, самоутвердился и сидит себе довольный, сам себе нравится, герой ептить

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.