Part3: Overcome the ‘Access Violation Exception’ in the FFMPEG
“Part1: Overcome the ‘Access Violation Exception’ in the FFMPEG ” presents a simple solution for “Access Violation Exception”. By further analyzing the root cause, we provide a better method in “Part2: Overcome the ‘Access Violation Exception’ in the FFMPEG ”. The later improves the performance of codec to some extension, because it enables all related ASM source codes, but it needs modify the complicated ASM source codes to eliminate the aligning instructions. From the view of maintenance, it will lead to take a high cost in future.
As mentioned before, Can I find the better solution to balance between performance and correction? En…, Maybe! But it needs understand GCC deeply and find workaround in this case.
Step 1: What do we see in the fft.c?
The key block of source codes is listed in the next table, and could you tell me what you find?
| DECLARE_ALIGNED_16(FFTSample, ff_cos_16[8]); DECLARE_ALIGNED_16(FFTSample, ff_cos_32[16]); DECLARE_ALIGNED_16(FFTSample, ff_cos_64[32]); DECLARE_ALIGNED_16(FFTSample, ff_cos_128[64]); DECLARE_ALIGNED_16(FFTSample, ff_cos_256[128]); DECLARE_ALIGNED_16(FFTSample, ff_cos_512[256]); DECLARE_ALIGNED_16(FFTSample, ff_cos_1024[512]); DECLARE_ALIGNED_16(FFTSample, ff_cos_2048[1024]); DECLARE_ALIGNED_16(FFTSample, ff_cos_4096[2048]); DECLARE_ALIGNED_16(FFTSample, ff_cos_8192[4096]); DECLARE_ALIGNED_16(FFTSample, ff_cos_16384[8192]); DECLARE_ALIGNED_16(FFTSample, ff_cos_32768[16384]); DECLARE_ALIGNED_16(FFTSample, ff_cos_65536[32768]); |
I guess that readers can get more than what I have. Herein, it’s my answer:
1. ff_cos_* are defined in the light of 16 bytes’ alignment.
2. ff_cos_* have not been initialized in these definitions.
Step 2: Which section will GCC put them into?
Unix C compilers have traditionally permitted multiple definitions of such variables in the different compilation units by placing the variables in a common section. To be compatible with Unix C, GCC select it as the default way in most targets. From the view of the previous investigation in Part1 and Part2, GCC takes some mistakes to align the variables’ address of common section when linking *.o built by different compilers. Following the clue, I ask myself “What will happen if I disable common section?” The obvious result is that they will be arranged into data section. OK, it is good. What will happen in the data section, and will it be same as common section? …?
WOW, too many questions for this exploration. I can not answer them all! So why not to take actions to find the truth? Let’s go!
Step 3: Append ‘-fno-common’ compiling option for FFMPEG
| $ ./configure --enable-memalign-hack --enable-shared --disable-static --enable-yasm --extra-cflags='-fno-common' && make && make install
For the detailed HOWTO, please refer to FFmpeg Understand(3. How to compile FFMPEG in Windows?) . |
Let’s have a rest and take a cup of tea, and we have enough time to enjoy our life:-).
Tick, tick, tick, …
Yeah, it is done! Check it! Cross our fingers!
| $ nm ./libavcodec/avcodec-52.dll | egrep 'ff_cos' 6af6305c T _ff_cos 6b3ee9f0 B _ff_cos_1024 6b3ee2f0 B _ff_cos_128 6b3ee210 B _ff_cos_16 6b3f61f0 B _ff_cos_16384 6b3ef1f0 B _ff_cos_2048 6b3ee3f0 B _ff_cos_256 6b3ee230 B _ff_cos_32 6b3fe1f0 B _ff_cos_32768 6b3f01f0 B _ff_cos_4096 6b3ee5f0 B _ff_cos_512 6b3ee270 B _ff_cos_64 6b40e1f0 B _ff_cos_65536 6b3f21f0 B _ff_cos_8192 6b1ef020 D _ff_cos_tabs |
Cool! It has been fixed!!!
After pleasure, I ask my again! What will I be paid for this operation? So I must read the GCC manual to disclosure my worry. I copy a segment from the manual of GCC.
| The ‘-fno-common’ option specifies that the compiler should place uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if the same variable is declared (without extern) in two different compilations, you will get a multiple-definition error when you link them. In this case, you must compile with ‘-fcommon’ instead. Compiling with ‘-fno-common’ is useful on targets for which it provides better performance, or if you wish to verify that the program will work on other systems which always treat uninitialized variable declarations this way. |
HOHO~~, no problem! I get an extra gift, performance, at the same time! HAHAHA…
[Summarization]
1. It should be a final solution to overcome the ‘Access Violation Exception’. All source codes of FFMPEG should not been modified and only add --extra-cflags='-fno-common' option when building them.
2. ‘-fno-common’ gives me an extra gift and take a good performance as the same time. As the mentioned by GCC, it should be a default compiling option if there are no multi-definitions of variables.
3. Both GCC4.3.0(Alpha) and GCC4.2.1 have this issue in the platform of MINGW. GCC4.4.0 has fixed this issue, but it can not work in the sharing mode of FFMPEG in the current official release.

本文介绍了一种解决FFMPEG中出现的访问违规异常的方法,通过禁用GCC的公共段特性,使得未初始化的全局变量放置到数据段中,从而避免了链接时的地址对齐问题。
1024

被折叠的 条评论
为什么被折叠?



