Opened 13 years ago

Closed 13 years ago

#3432 closed Bugs (fixed)

Boost:Test pointer error with g++ 64-bit on Mac OS X 10.6 Snow Leopard

Reported by: Justus Calvin <justus.c79@…> Owned by: Gennadiy Rozental
Milestone: Component: test
Version: Boost 1.40.0 Severity: Problem
Keywords: test mac "snow leopard" pointer 64-bit Cc:

Description

When I compile a program which uses Boost:Test on Mac OS X 10.6 "Snow Leopard" for 64-bit architecture, I get an error when the program is run. To demonstrate this error, I creating a sample program (see attached file), which contains 10 test suites, each containing 10 test cases. The error only appears after a certain number of test suites/cases have been added to the program, because I could not reproduce the error with 10 test suites with 1 test case each. The compile commands and out put are:

$ g++ -g -c -fmessage-length=0 -o"src/UnitTest.o" "../src/UnitTest.cpp"
$ g++ -o "UnitTest"  ./src/UnitTest.o
$ ./UnitTest
Running 100 test cases...

*** No errors detected
UnitTest(73438) malloc: *** error for object 0x3000100600630: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap

I then tried compiling this with g++ 4.0.1 (apple), g++ 4.2.1 (apple), g++ 4.4.1, and icpc 11.1 with and without -m32 option; all on Mac OS X 10.6. In addition, I also compiled my test program with g++ 4.3.3 on Ubuntu Linux 9.04 (x86_64 version) with and without -m32 option. Here are the results of those tests.

g++ Mac OS X 10.6: v 4.0.1 32bit: Pass v 4.0.1 64bit: Fail v 4.2.1 32bit: Pass v 4.2.1 64bit: Fail v 4.4.1 32bit: Pass v 4.4.1 64bit: Fail

icpc Mac OS X 10.6: v 11.1 32bit: Pass v 11.1 64bit: Pass

g++ Linux x86_64: v 4.3.3 64bit: Pass

It appears that the error only occurs with g++ 64bit code on Mac OS X.

While debugging the program I found that the error occurs in boost/test/impl/framework.ipp in void boost::unit_test::framework_imp::clean(), when delete is called. However, I do not think the error is in this function. Since the problem is not present when it is compiled as a 32-bit program, it is likely caused by a 64-bit value being written to a 32-bit address or something like that.

Attachments (3)

UnitTest.cpp (6.9 KB ) - added by Justus Calvin <justus.c79@…> 13 years ago.
double_free.cpp (202 bytes ) - added by janm@… 13 years ago.
Test case with a single unit test.
framework.ipp.patch (756 bytes ) - added by janm@… 13 years ago.
Patch to resolve the problem.

Download all attachments as: .zip

Change History (8)

by Justus Calvin <justus.c79@…>, 13 years ago

Attachment: UnitTest.cpp added

comment:1 by janm@…, 13 years ago

I see this problem on Mac OSX 10.6.1 as in the original report, and also on FreeBSD 7.2-STABLE, 64 bit version. I do not see the problem on 32 bit Windows XP with Visual C++ 2005 Express.

comment:2 by Justus Calvin <justus.c79@…>, 13 years ago

If I remember correctly, Mac OS X is a derivative of FreeBSD. I do not know how much they have in common today, but it is possible that it is a bug which still exists in the two OS's.

by janm@…, 13 years ago

Attachment: double_free.cpp added

Test case with a single unit test.

comment:3 by janm@…, 13 years ago

For me it fails in the attached example with a single case on FreeBSD. On OS X I need more test cases to show the problem.

The point of failure is the same on both platforms.

On OS X and FreeBSD background: Possible, but also possibly not. I'd prefer not to jump to conclusions.

by janm@…, 13 years ago

Attachment: framework.ipp.patch added

Patch to resolve the problem.

comment:4 by janm@…, 13 years ago

Please see the attached patch. This resolves the problem for me on OS X and FreeBSD.

On OS X the single test case example can be made to fail by setting the "MallocScribble" environment variable.

The problem is that the delete in framework_impl::clear() happens through a reference to the actual pointer in the m_test_units container, and the destructor of the object removes itself from the container. Once the object is removed from the container (in the the destructor) the reference is no longer valid, and the underlying call to free() uses the now-invalid reference.

Solution: Keep a copy of the pointer to be deleted on the stack.

comment:5 by Gennadiy Rozental, 13 years ago

Resolution: fixed
Status: newclosed

(In [56467]) apparently compiler might want to examine tu.second twice: before and after calling destructor Fixes #2889 Fixes #3432 Fixes #2647

Note: See TracTickets for help on using tickets.