[flac-dev] sf bug 256 - Virtual functions in destructor

Ralph Giles giles at thaumas.net
Mon Aug 19 19:55:49 PDT 2013


In 2007, user reported a segfault in
FLAC::Encoder::File::progress_callback() when called from ~Stream().

Original report at https://sourceforge.net/p/flac/bugs/256/


Hello! Sorry, english is not my best language.

I use libFLAC++ API. I have some problems. In libFLAC API all OK.

Unhandled exception at 0x00000000 in Test.exe: 0xC0000005: Access
violation reading location 0x00000000.

Call stack
00000000()
Test.exe!FLAC::Encoder::File::progress_callback_(const
FLAC__StreamEncoder * encoder=0x003571f8, unsigned __int64
bytes_written=2156194, unsigned __int64 samples_written=845544, unsigned
int frames_written=734, unsigned int total_frames_estimate=0, void *
client_data=0x0012fe1c) Line 507 + 0x2a bytes C++
Test.exe!file_write_callback_(const FLAC__StreamEncoder *
encoder=0x003571f8, const unsigned char * buffer=0x0047daa8, unsigned
int bytes=2804, unsigned int samples=1128, unsigned int
current_frame=733, void * client_data=0x0012fe1c) Line 4487 + 0x7a bytes C
Test.exe!write_frame_(FLAC__StreamEncoder * encoder=0x003571f8, const
unsigned char * buffer=0x0047daa8, unsigned int bytes=2804, unsigned int
samples=1128, int is_last_block=1) Line 2712 + 0x3a bytes C
Test.exe!write_bitbuffer_(FLAC__StreamEncoder * encoder=0x003571f8,
unsigned int samples=1128, int is_last_block=1) Line 2622 + 0x19 bytes C
Test.exe!process_frame_(FLAC__StreamEncoder * encoder=0x003571f8, int
is_fractional_block=1, int is_last_block=1) Line 3119 + 0x16 bytes C
Test.exe!FLAC__stream_encoder_finish(FLAC__StreamEncoder *
encoder=0x003571f8) Line 1334 + 0xf bytes C
Test.exe!FLAC::Encoder::Stream::~Stream() Line 57 + 0xc bytes C++
Test.exe!FLAC::Encoder::File::~File() Line 448 + 0x8 bytes C++
Test.exe!MyFile::~MyFile() + 0x2e bytes C++
Test.exe!main() Line 188 + 0xf bytes C++
Test.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C
Test.exe!mainCRTStartup() Line 403 C

src\libflac++\stream_encoder.cpp
void File::progress_callback_(const ::FLAC__StreamEncoder *encoder,
FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned
frames_written, unsigned total_frames_estimate, void *client_data)
{
(void)encoder;
FLAC__ASSERT(0 != client_data);
File *instance = reinterpret_cast<File *>(client_data);
FLAC__ASSERT(0 != instance);
instance->progress_callback(bytes_written, samples_written,
frames_written, total_frames_estimate); // Here!!! progress_callback = 0
}

I think about this problem (am i right?):

The C++ Programming Language Special Edition (Third Edition) Bjarne
Stroustrup

15.4.3 Class Object Construction and Destruction
A class object is more than simply a region of memory (§4.9.6). A class
object is built from ‘‘raw
memory’’ by its constructors and it reverts to ‘‘raw memory’’ as its
destructors are executed. Construction
is bottom up, destruction is top down, and a class object is an object
to the extent that it
has been constructed or destroyed. This is reflected in the rules for
RTTI, exception handling
(§14.4.7), and virtual functions.
It is extremely unwise to rely on details of the order of construction
and destruction, but that
order can be observed by calling virtual functions, dynamic_ cast, or
typeid (§15.4.4) at a point
where the object isn’t complete. For example, if the constructor for
Component in the hierarchy
from §15.4.2 calls a virtual function, it will invoke a version defined
for Storable or Component,
but not one from Receiver, Transmitter, or Radio. At that point of
construction, the object isn’t
yet a Radio; it is merely a partially constructed object. It is best to
avoid calling virtual functions
during construction and destruction.

Email address: visor at nextmail.ru


More information about the flac-dev mailing list