Large Fixed-Size Arrays In `ClassTable::Print()` Cause App Crash On Android Emulator
Introduction
In the src\third_party\dart\runtime\vm\class_table.cc
file, the void ClassTable::Print()
function uses two large fixed-size character arrays, pushArr[1600000]
and classText[2500000]
, to store library URLs and class information. However, when running on an Android emulator, these arrays can lead to the application crashing and failing to open, likely due to stack overflow from their excessive size. In this article, we will delve into the issue, reproduce the problem, and propose a solution to fix the app crash.
Description
The void ClassTable::Print()
function is responsible for printing class information to a dump file. It uses two large fixed-size character arrays, pushArr[1600000]
and classText[2500000]
, to store library URLs and class information. These arrays are allocated on the stack, which can lead to stack overflow when the app is running on an Android emulator.
Steps to Reproduce
To reproduce the issue, follow these steps:
Step 1: Set up an Android emulator
- Path:
avd\Pixel_9_Pro_XL_API_35.avd
- Target:
android-35
Step 2: Build and run a Flutter app
- Flutter Version:
3.7.12
- Engine Commit:
1a65d409c7a1438a34d21b60bf30a6fd5db59314
- Snapshot Hash:
adb4292f3ec25074ca70abcd2d5c7251
Step 3: Trigger the ClassTable::Print()
function
- Trigger the
ClassTable::Print()
function with a moderate-to-large number of classes or libraries (e.g., a typical Flutter app with many dependencies).
Step 4: Attempt to launch the app on the emulator
- Attempt to launch the app on the emulator.
Expected Behavior
The app should launch successfully and write class/library information to the dump file without issues.
Actual Behavior
The app crashes and fails to open on the emulator. This is likely due to the large stack allocations of pushArr[1600000]
(1.6MB) and classText[2500000]
(2.5MB) exceeding the stack size limit, causing a stack overflow.
Affected Code
File: src\third_party\dart\runtime\vm\class_table.cc
Function: void ClassTable::Print()
Relevant code snippet:
void ClassTable::Print() {
OS::PrintErr("reFlutter");
char pushArr[1600000] = "";
Class& cls = Class::Handle();
String& name = String::Handle();
for (intptr_t i = 1; i < classes_.num_cids(); i++) {
if (!HasValidClassAt(i)) {
continue;
}
cls = At(i);
if (cls.ptr() != nullptr) {
name = cls.Name();
auto& funcs = Array::Handle(cls.functions());
if (funcs.Length() > 1000) {
continue;
}
char classText[2500000] = "";
// ... string concatenation logic ...
}
}
// ... file writing logic ...
}
Proposed Solution
To fix the app crash, we propose the following solution:
- Replace
pushArr[1600000]
with a dynamic structure (e.g.,GrowableArray<const char*>
) to store library URLs, avoiding large stack allocations. - Replace
classText[2500000]
withGrowableArray<char>
to dynamically build class text, preventing stack overflow. - This will ensure the app can handle varying amounts of data without crashing.
By implementing this solution, we can prevent the app from crashing due to stack overflow and ensure that it can handle large amounts of data without issues.
Conclusion
Introduction
In our previous article, we discussed the issue of large fixed-size arrays in the ClassTable::Print()
function causing app crashes on Android emulators. In this Q&A article, we will answer some frequently asked questions related to this issue.
Q: What are the large fixed-size arrays in ClassTable::Print()
?
A: The large fixed-size arrays in ClassTable::Print()
are pushArr[1600000]
and classText[2500000]
. These arrays are used to store library URLs and class information, respectively.
Q: Why do these arrays cause app crashes on Android emulators?
A: These arrays cause app crashes on Android emulators because they are allocated on the stack, which can lead to stack overflow when the app is running on an Android emulator. The stack size limit on Android emulators is typically smaller than on physical devices, making it more likely for the app to crash.
Q: What is the impact of these arrays on app performance?
A: The impact of these arrays on app performance is significant. When the app is running on an Android emulator, the large stack allocations of pushArr[1600000]
and classText[2500000]
can cause the app to slow down or even crash.
Q: How can I reproduce the issue?
A: To reproduce the issue, follow these steps:
- Set up an Android emulator with the following configuration:
- Path:
avd\Pixel_9_Pro_XL_API_35.avd
- Target:
android-35
- Path:
- Build and run a Flutter app with:
- Flutter Version:
3.7.12
- Engine Commit:
1a65d409c7a1438a34d21b60bf30a6fd5db59314
- Snapshot Hash:
adb4292f3ec25074ca70abcd2d5c7251
- Flutter Version:
- Trigger the
ClassTable::Print()
function with a moderate-to-large number of classes or libraries (e.g., a typical Flutter app with many dependencies). - Attempt to launch the app on the emulator.
Q: What is the expected behavior of the app?
A: The expected behavior of the app is that it should launch successfully and write class/library information to the dump file without issues.
Q: What is the actual behavior of the app?
A: The actual behavior of the app is that it crashes and fails to open on the emulator.
Q: How can I fix the app crash?
A: To fix the app crash, you can replace pushArr[1600000]
with a dynamic structure (e.g., GrowableArray<const char*>
) to store library URLs, avoiding large stack allocations. You can also replace classText[2500000]
with GrowableArray<char>
to dynamically build class text, preventing stack overflow.
Q: What are the benefits of using dynamic structures instead of fixed-size arrays?
A: The benefits of using dynamic structures instead of fixed-size arrays are:
- They can handle varying amounts of data without crashing.
- They can prevent stack overflow and improve app performance.
- They can make the app more robust and reliable.
Conclusion
In conclusion, the large fixed-size arrays in ClassTable::Print()
can cause app crashes on Android emulators. By understanding the issue and its impact on app performance, you can take steps to fix the problem and improve the overall user experience.