Recently in the project, I found that when using the Qwebview provided by Qt4.8.5 to interact with the Web page,
M_pwebview->page ()->mainframe ()->evaluatejavascript (TMP);
The QtWebKitd4.dll module occasionally crashes,
Interrupt View Call stack (load qtwebkitd4.pdb to see correct stack information)
Finally stop at QT Stackbounds::checkconsistency. From the Stack class name and function name, it may be related to the stack, try to look at the source file, find the function definition
function is very short, with the specific business logic has nothing to do, you can get the release mode function directly back, debug mode, on the stack to create an object to obtain the stack pointer size, assert according to the stack growth direction,
Check the relationship of the stack pointer with M_origin and m_bound at this point. The inference from the name is to compare the stack base with the stack boundary. Continue to look at the code, how to give these two assignments.
Under the X86CPU with the MSVC compiler, the stack base m_origin gets the base address of the current thread's stack through the NT_TIB thread information block saved in the FS register, no problem
What about the stack boundary, M_bound?
Through the source of comments, it seems to want to get through the NT_TIB, but did not do (later verify that this method gets the stack boundary is unreliable, only the submitted stack size can be obtained. qt5.4 provides a new way to get, and later modifications are based on this.
Go ahead and see how QT does it.
Go to function definition:
Qt to the stack boundary size fixed to 512kB, obviously does not apply to all platforms, the source code note also gives the description this code unsafely guesses stack sizes!,windows, wince and other platforms, May is work wrong.
Knowing that it is not OK, but still set a fixed value, and is a common platform-wide value, think we have in the past projects have also made a similar compromise?
Visible implementation of Qt4.8.5 is still a relatively hasty, not a stable version.
Look at the back qt5.4 when (in the middle which version began to change, this does not concern: ), the entire platform is code acquisition, feeling very reliable, at least in the window platform. (QT team efficiency is still possible!) )
The cause of the problem is roughly fixed, but where does it lead to a lot of use of the stack space?
Guessing 1:qtwebkit internal calls, consuming a lot of stack space.
Verify: 1.1 Create a new project, load the page with Qwebview m_pwebview->load (qurl ("xxx"));
1.2 Register JS Call Object M_pwebview->page ()->mainframe ()->addtojavascriptwindowobject ("Servers", this);
1.3 Declaring the interface for JS invocation
int Js2qt::maincall (QString szcalloperate,qstring szexterndata)
{
....
M_pwebview->page ()->mainframe ()->evaluatejavascript (TMP);
}
1.4 View Stack EBP (stack base address) with ESP (stack top pointer) before executing JS. The current consumption of ebp-esp only a few k, belonging to the normal phenomenon.
1.5 Execute JS, normal.
Guess 2: Project Engineering has consumed a lot of stack space before entering the Qwebview call chain.
Verification: Before entering the Maincall breakpoint, observed into the Maincall, Ebp-esp instantly consumes more than 850KB of the stack space (the default 1MB),
Execute JS, there is an interrupt. 850KB already more than 512KB, debug mode Qtwebkit as long as the implementation of Stackcheck, the inevitable assert.
The same situation Relese will not crash, just verify that the previous source code in Relese mode does not check the stack.
Result: View the implementation of Maincall in the actual project, which does declare a large number of temporary objects and consumes a lot of stack space.
Change of opinion:
|
Main project (Generate EXE's project) properties |
Qtwebkit |
Debug |
Project Properties-"linker-" system modify stack reserve size (recommended 2097152) Other default 0 |
- Reference qt5.4 fix m_bound stack boundary with stack base address, recompile QtWebKit.sln (attachment replacement qt4.8.5 recompile WebKit.sln project)
- Binary editor directly find the corresponding code binary, modify the number size (suitable for local use)
- Increase M_bound stack boundary fixed value, recompile QtWebkit.sln project (not recommended)
|
Release |
Project Properties-"linker-" system modify stack reserve size (recommended 2097152) Other default 0 |
The Qtwebkit does not check for stack usage in release mode. If there is not enough stack space, it crashes directly. |
Q&a
- Same operation why debug mode must crash, but release mode does not crash?
A: Because the Qtwebkit Stackbounds class is responsible for the stack boundary check, think that the size of the stack fixed at 512kB, and the main thread of the default stack 1MB, when the main thread uses more than 512kB of stack space, Qtwebkit will collapse,
But in release mode, Qtwebkit does not do stack check, as long as the main thread use stack not more than 1MB, the program will not crash.
- Why do some interaction with JS, the program will crash?
A: Using the Qwebview kernel, and JS interaction is through the xxx::maincall of our project to complete the distribution, the various arrays declared in Maincall consumes a lot of stack space,
At this point, we have used around 850kB, when the function calls continue to occur, the stack is further consumed, and when some operations need to consume a bit more stack space, a crash occurs, and if the crash
VS Compiled library (do not actively do stack check, not active interrupt), will be friendly hint StackOverflow, crash in other libraries (do not actively do stack check, not active interrupt), it will appear inexplicably.
!! Hidden issues, although the expansion of the default stack size, can solve the problem, but, change the default stack size caused by the problem?
- The default stack size we set will work if our project eventually generates Xxx.exe to serve the process.
- If our project generates Xxx.dll or Xxx.ocx. Our service is loaded by IE (other process), the stack of the main thread is determined by the loading process, and the large stack of our engineering settings will not work. (Workaround: Modify IE default stack size field, it is convenient to use the PE tool)
In short, the root of the problem is that a large number of use of stack resources in a function, is not a good program design style, on the current and future problems will arise, two points of their own suggestions
- A function should not be too long, it should be in accordance with the actual business distribution processing, more functions responsible for different operations, while a function inside do not consume too much stack space, it is possible to cause after the function call, StackOverflow.
- Use the standard library container to manage a large number of temporary objects (container objects allocate space on the stack, the contents of the container are allocated on the heap, the heap is freed by the standard library, and there is some reliability).
Attachment: Manually modify the QtWebKitd4.dll file to change the fixed stack size of the Qtwebkit settings.
Next breakpoint observe M_bound's instruction address
Instruction address 0x10ec3636 View module load address: 0x10000000 The file offset address 0x00ec3626
Open the QtWebKit4d.dll with the binary editor (debug is required) to find 0x00ec3626 or direct search content 2d00000800
00 00 08 00 corresponding Assembly instruction Sub eax 80000h note for small-endian byte order
Save it.
Replace QtWebkitd4.dll breakpoint View
Modification succeeded
Thinking of Qt4.8.5 qtwebkit qwebview user stack check crash problem