提问人:RedStoneMatt 提问时间:6/14/2023 更新时间:6/14/2023 访问量:120
Android C++新运算符导致“malloc(4294967295) 失败,errno 12”
Android C++ new operator leads to "malloc(4294967295) failed, errno 12"
问:
TD公司;博士
我正在将我的一个 C++ 项目移植到 android,但是当使用运算符时,它实际上出于某种原因调用,这会导致内存不足错误,即使调试证明我的类大小正确(并且该项目在为 Windows 构建时有效)。new
malloc(4294967295)
这会导致应用程序在物理 Android 设备上卡在黑屏上,或者只是在模拟器上崩溃
上下文
我目前正在尝试将我的 SDL 项目移植到 android。
为此,我按照官方 SDL 存储库中的教程中的说明进行操作。 此外,我按照本教程将 SDL_image 模块以及 SDL_ttf 添加到我的项目中。
问题
构建应用程序工作正常,但一旦启动,它就会卡在黑屏上:
弄清楚它发生的原因(调试)
“打印”调试
因此,我将手机插入计算机,并尝试使用打印来调试adb
的问题,这是我发现的:
为了初始化 SDL 和其他组件,我的游戏函数如下所示:main
int main(int argc, char* argv[]) {
__android_log_print(ANDROID_LOG_DEBUG, "DEBUG", "Starting");
srand(time(NULL));
const int targetFPS = 60;
const int frameDelay = 1000 / targetFPS;
// Init
__android_log_print(ANDROID_LOG_DEBUG, "DEBUG", "Constructing Game class of size: %lX", sizeof(Game));
Game* game = new Game(argc, argv);
__android_log_print(ANDROID_LOG_DEBUG, "DEBUG", "Game constructed");
__android_log_print(ANDROID_LOG_DEBUG, "DEBUG", "Initializing");
int errInit = game->init("SAE201205", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
__android_log_print(ANDROID_LOG_DEBUG, "DEBUG", "Initialized: %d", errInit);
if (errInit == 0) {
while (game->running()) {
/* Game Logic here */
}
game->clean();
}
delete game;
return 0;
}
请注意这些调用,它们在这里帮助调试函数。__android_log_print
在我的手机上启动应用程序并使用 捕获手机日志时,可以看到以下几行:adb logcat
06-14 08:34:35.471 8262 8326 V SDL : Running main function SDL_main from library /data/app/~~F1pn5U_H13LZFzCic5LLyA==/org.libsdl.app-AHd89RMgz8bystTw8XwclA==/lib/arm/libmain.so
06-14 08:34:35.471 8262 8326 V SDL : nativeRunMain()
06-14 08:34:35.471 8262 8326 D DEBUG : Starting
06-14 08:34:35.471 8262 8326 D DEBUG : Constructing Game class of size: 98
06-14 08:34:35.472 8262 8326 W libc : malloc(4294967295) failed: returning null pointer, errno: 12
然后应用程序中断。我写的更多印刷品从未被印刷过。
可以看出,当使用 new 运算符时,它会调用 .问题是,它不是用我的 Game 类的大小(0x98,如上所示)调用它,而是用 4294967295 的大小(=0xFFFFFFFF,如果有符号,则为 -1),因此导致 malloc 抛出错误 12(“内存不足”)。malloc
这完全没有意义,因为我显然没有尝试分配 4 GB 的内存,并且由于编译器在打印时正确计算了我的 Game 类的大小,因此它应该尝试分配正确的大小。
拆卸
为了确保确实调用了新的运算符,我在 Ghidra 中打开了包含代码的编译文件。
与我们感兴趣的内容相对应的说明如下:.so
可以看出,新运算符确实被调用了。它链接到一个外部函数(因为它是一个共享库构建),但没有错误的 malloc 的痕迹。
但是,传递给新运算符的分配大小似乎代替了打印的 .Ghidra 显示的大小很可能是正确的,因为 android 打印格式似乎存在与此处描述的问题相关的问题(使用 时,编译器会发出警告并要求使用 ,但在使用时会发出警告并要求使用 )。0x108
0x98
%X
%lX
%lX
%X
我的 Windows 版本给出的大小为 .我关于这种大小差异的理论是,指针大小以及其他原生结构可能不同。0x130
无论哪种方式,无论正确的大小,它都远非 ,因此 malloc 误差不太可能与大小差异有关。0xFFFFFFFF
我的配置
以下是我的项目的配置方式。
首先,它是一个 Gradle 项目,其结构与官方 SDL 存储库中的结构相同:
我的应用文件(这里)如下:Application.mk
# Uncomment this if you're using STL in your project
# You can find more information here:
# https://developer.android.com/ndk/guides/cpp-support
APP_STL := c++_shared
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
# Min runtime API level
APP_PLATFORM=android-16
可以看出,我取消了该行的注释,因为我的项目使用了很多 STL 函数。它被设置为默认,但我尝试过并面临相同的结果。此外,并且已弃用,无论如何都不适用于 SDL 项目。APP_STL
c++_shared
c++_static
gnustl_shared
gnustl_static
位于同一文件夹(此处)中的文件如下所示:CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(GAME)
# armeabi-v7a requires cpufeatures library
# include(AndroidNdkModules)
# android_ndk_import_module_cpufeatures()
# SDL sources are in a subfolder named "SDL"
add_subdirectory(SDL)
# Compilation of companion libraries
add_subdirectory(SDL_image)
#add_subdirectory(SDL_mixer)
add_subdirectory(SDL_ttf)
# Your game and its CMakeLists.txt are in a subfolder named "src"
add_subdirectory(src)
位于我的项目的 C++ 源文件夹(此处)中的文件如下所示:Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
SDL_PATH := ../SDL
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include $(LOCAL_PATH)/../SDL_image/include $(LOCAL_PATH)/../SDL_ttf/include $(LOCAL_PATH)/../include
# Add your application source files here...
LOCAL_SRC_FILES := main.cpp <all my other cpp files here, irrelevant so not including them>
LOCAL_SHARED_LIBRARIES := SDL2 SDL2_image SDL2_ttf
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
include $(BUILD_SHARED_LIBRARY)
据我所知,我没有编辑任何其他配置文件(并检查过)。请随时询问您是否需要我未在此处包含的特定文件的内容。
我现在在哪里
这种问题太具体了,很难找到遇到任何接近这个问题的人,所以我什么也没找到
提醒一下,该项目编译并适用于 Windows,我在这里遇到的问题是 android 独有的。
如果我能推测,我会说 c++ 库只是一个我错过的选项来支持运算符,但我找不到任何东西,而且我对 android 开发非常陌生,所以我不能肯定地说。new
答:
我发现了问题所在。
正如评论者所指出的,Game 类的构造函数有问题,而不是内存分配本身。
我以为我已经删除了所有可能导致崩溃的东西,但那是不知道即使没有明确说明类的成员也会被构造,这导致了崩溃,因为他们中的一些人以 Windows 方式请求文件。
不好意思!
评论
Game
std::vector
Game* game = new Game(argc, argv);
Game game(argc, argv);
main
game