|
From: Samofatov, N. <NSa...@br...> - 2004-07-28 22:41:55
|
Hi, All!
I'm trying to use Valgrind 2.1.2 with Firebird memory pools.
In the simplest case, Firebird memory pool is a collection of mmap'd
extents which are than sub-allocated.
To let Valgrind know about firebird memory pools I made the following:
1) Right after pool is created I do
VALGRIND_CREATE_MEMPOOL(pool, VALGRIND_REDZONE, 0);
2) Right before pool destruction I do
VALGRIND_DESTROY_MEMPOOL(pool);
3) After I allocated block (reserving space at the beginning and end for
Valgrind red zones) I do
VALGRIND_MEMPOOL_ALLOC(this, result, requested_size);
4) When pool user requests to free the block, first I do
VALGRIND_MEMPOOL_FREE(this, block);
then I move block pointer to a fixed-size FIFO queue doing
VALGRIND_MAKE_NOACCESS when block enters queue and
call VALGRIND_MAKE_READABLE && VALGRIND_MAKE_WRITABLE &&
VALGRIND_DISCARD and internally deallocate block pushed out of the
queue.
The purpose of this queue is to detect reads of deallocated memory.
My immediate problem is that Valgrind thinks that memory pools manager
performs invalid reads and writes. Basically, it complains a lot when I
fill the headers of memory blocks:
--------------
// Cut a piece at the end of block in hope to avoid
structural
// modification of free blocks tree
current->block->small.mbk_length -=3D
MEM_ALIGN(sizeof(MemoryBlock)) + size;
blk =3D next_block(current->block);
blk->mbk_pool =3D this; ///// <----- VALGRIND first compaint
is here
blk->mbk_flags =3D MBK_USED | (current->block->mbk_flags &
MBK_LAST);
#ifdef DEBUG_GDS_ALLOC
blk->mbk_file =3D file;
blk->mbk_line =3D line;
#endif
current->block->mbk_flags &=3D ~MBK_LAST;
blk->mbk_type =3D type;
blk->small.mbk_length =3D size;
blk->small.mbk_prev_length =3D
current->block->small.mbk_length;
if (!(blk->mbk_flags & MBK_LAST))
next_block(blk)->small.mbk_prev_length =3D
blk->small.mbk_length;
--------------
Complaints look like this:
--------------
.................
=3D=3D17141=3D=3D Invalid write of size 4
=3D=3D17141=3D=3D at 0x34305FB7:
Firebird::MemoryPool::internal_alloc(unsigned, short)
(../src/common/classes/alloc.cpp:969)
=3D=3D17141=3D=3D by 0x34304ABC:
Firebird::MemoryPool::allocate_nothrow(unsigned, short)
(../src/common/classes/alloc.cpp:554)
=3D=3D17141=3D=3D by 0x34173375: gds__alloc (../src/jrd/gds.cpp:3679)
=3D=3D17141=3D=3D by 0x342EBAB0: ALLR_alloc(unsigned long)
(../src/remote/allr.cpp:78)
=3D=3D17141=3D=3D Address 0x347EC70C is 63244 bytes inside a block of =
size
65536 alloc'd
=3D=3D17141=3D=3D at 0x343041E2:
Firebird::MemoryPool::external_alloc(unsigned&)
(../src/common/classes/alloc.cpp:337)
=3D=3D17141=3D=3D by 0x343057CE:
Firebird::MemoryPool::internal_create(unsigned, Firebird::MemoryPool*,
Firebird::MemoryStats&) (../src/common/classes/alloc.cpp:819)
=3D=3D17141=3D=3D by 0x34309D90:
Firebird::MemoryPool::createPool(Firebird::MemoryPool*,
Firebird::MemoryStats&) (../src/common/classes/alloc.h:280)
=3D=3D17141=3D=3D by 0x34307027:
__static_initialization_and_destruction_0(int, int)
(../src/common/classes/alloc.cpp:233)
=3D=3D17141=3D=3D
=3D=3D17141=3D=3D Invalid write of size 2
=3D=3D17141=3D=3D at 0x34305FCB:
Firebird::MemoryPool::internal_alloc(unsigned, short)
(../src/common/classes/alloc.cpp:970)
=3D=3D17141=3D=3D by 0x34304ABC:
Firebird::MemoryPool::allocate_nothrow(unsigned, short)
(../src/common/classes/alloc.cpp:554)
=3D=3D17141=3D=3D by 0x34173375: gds__alloc (../src/jrd/gds.cpp:3679)
=3D=3D17141=3D=3D by 0x342EBAB0: ALLR_alloc(unsigned long)
(../src/remote/allr.cpp:78)
=3D=3D17141=3D=3D Address 0x347EC710 is 63248 bytes inside a block of =
size
65536 alloc'd
=3D=3D17141=3D=3D at 0x343041E2:
Firebird::MemoryPool::external_alloc(unsigned&)
(../src/common/classes/alloc.cpp:337)
=3D=3D17141=3D=3D by 0x343057CE:
Firebird::MemoryPool::internal_create(unsigned, Firebird::MemoryPool*,
Firebird::MemoryStats&) (../src/common/classes/alloc.cpp:819)
=3D=3D17141=3D=3D by 0x34309D90:
Firebird::MemoryPool::createPool(Firebird::MemoryPool*,
Firebird::MemoryStats&) (../src/common/classes/alloc.h:280)
=3D=3D17141=3D=3D by 0x34307027:
__static_initialization_and_destruction_0(int, int)
(../src/common/classes/alloc.cpp:233)
=3D=3D17141=3D=3D
=3D=3D17141=3D=3D Invalid write of size 2
=3D=3D17141=3D=3D at 0x34305FEB:
Firebird::MemoryPool::internal_alloc(unsigned, short)
(../src/common/classes/alloc.cpp:976)
=3D=3D17141=3D=3D by 0x34304ABC:
Firebird::MemoryPool::allocate_nothrow(unsigned, short)
(../src/common/classes/alloc.cpp:554)
=3D=3D17141=3D=3D by 0x34173375: gds__alloc (../src/jrd/gds.cpp:3679)
=3D=3D17141=3D=3D by 0x342EBAB0: ALLR_alloc(unsigned long)
(../src/remote/allr.cpp:78)
=3D=3D17141=3D=3D Address 0x347EC712 is 63250 bytes inside a block of =
size
65536 alloc'd
=3D=3D17141=3D=3D at 0x343041E2:
Firebird::MemoryPool::external_alloc(unsigned&)
(../src/common/classes/alloc.cpp:337)
=3D=3D17141=3D=3D by 0x343057CE:
Firebird::MemoryPool::internal_create(unsigned, Firebird::MemoryPool*,
Firebird::MemoryStats&) (../src/common/classes/alloc.cpp:819)
=3D=3D17141=3D=3D by 0x34309D90:
Firebird::MemoryPool::createPool(Firebird::MemoryPool*,
Firebird::MemoryStats&) (../src/common/classes/alloc.h:280)
=3D=3D17141=3D=3D by 0x34307027:
__static_initialization_and_destruction_0(int, int)
(../src/common/classes/alloc.cpp:233)
.....................
--------------
In this case I marked mmap'd block with VALGRIND_MALLOCLIKE_BLOCK. If I
do not mark the block message persists, but says block is not stack'd,
alloc'd or free'd.
I have a couple questions.
1) Is writing suppressions right way to deal with the problem I'm
having? Or I should be marking my extents somehow?
2) Is my approach of interfacing with Valgrind generally correct?
Firebird pools manager is written in C++ and is relatively isolated so I
can create small testcases if needed.
Nickolay Samofatov
|
|
From: Nicholas N. <nj...@ca...> - 2004-07-29 08:32:48
|
On Wed, 28 Jul 2004, Samofatov, Nickolay wrote: > In this case I marked mmap'd block with VALGRIND_MALLOCLIKE_BLOCK. If I > do not mark the block message persists, but says block is not stack'd, > alloc'd or free'd. > > I have a couple questions. > 1) Is writing suppressions right way to deal with the problem I'm > having? Or I should be marking my extents somehow? > 2) Is my approach of interfacing with Valgrind generally correct? Off the top of my head, your basic approach seems to be right, but I haven't checked the details thoroughly. Have you got the redzones right? If you have, for example, a 100-byte payload and 4-byte redzones, you'll need a 108 byte block (plus any extra admin words used by your allocator, but you don't need to tell Valgrind about that. You shouldn't be using suppressions here, if everything was done right it should just work. If I were you, I would pull the memory allocator out into the smallest possible program, and experiment with that. I find that a good technique in general when experimenting with an unfamiliar language feature or something like this, because it's much easier to work out what's going on when it's not buried inside something larger. HTH N |