gradle Android C++新运算符导致“malloc(4294967295)failed,errno 12”

lyr7nygr  于 2023-06-23  发布在  Android
关注(0)|答案(1)|浏览(167)

TD;DR

我正在将我的一个C++项目移植到android上,但是当使用new运算符时,它实际上由于某种原因调用了malloc(4294967295),这导致了内存不足错误,尽管调试证明我的类大小正确(并且该项目在为Windows构建时可以工作)。
这会导致应用程序在物理Android设备上出现黑屏,或者在模拟器上崩溃

Context

我目前正在尝试将我的SDL项目移植到Android上。
为此,我遵循了the tutorial located in the official SDL repo的说明。此外,我遵循this tutorial将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运算符时,它调用malloc。问题是,它不是用Game类的大小(0x 98,如上所述)调用它,而是用4294967295(= 0xFFFFFF,如果有符号,则为-1)调用它,因此导致malloc抛出错误12(“内存不足”)。
这是完全没有意义的,因为我显然没有尝试分配4GB的内存,而且由于我的Game类的大小在打印时被编译器正确计算,所以它应该尝试分配正确的大小。

拆解

为了确保确实调用了new运算符,我打开了编译后的.so文件,其中包含我在Ghidra中的代码。对应于我们感兴趣的指令如下:


可以看出,新操作符确实被调用了。它链接到一个外部函数(因为它是一个共享库构建),但没有错误malloc的痕迹。
但是,传递给新运算符的分配大小似乎是0x108,而不是打印的0x98。Ghidra显示的大小可能是正确的,因为Android打印格式似乎存在与此处描述的问题无关的问题(当使用%X时,编译器警告并要求使用%lX,但当使用%lX时,它警告并要求使用%X)。
我的Windows版本提供了0x130的大小。我对这种大小差异的理论是,指针大小以及其他本机结构可能不同。
无论哪种方式,无论正确的大小是多少,它都远远不是0xFFFFFFFF,因此malloc错误不太可能与大小差异有关。

我的配置

下面是我的项目是如何配置的。
首先,它是一个Gradle项目,遵循the same structure as in the official SDL repo

我的应用程序的Application.mk文件(here)如下:

# 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

可以看出,我取消了APP_STL行的注解,因为我的项目使用了很多STL函数。默认设置为c++_shared,但我尝试过c++_static,并面临相同的结果。此外,gnustl_sharedgnustl_static已被弃用,无论如何都不适用于SDL项目。
位于同一文件夹(here)中的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++源文件夹(here)中的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++库只是有一个选项,我错过了支持new操作符,但我找不到任何东西,而且我对android开发非常陌生,所以我不能肯定。

yptwkmov

yptwkmov1#

我发现问题了。
正如评论者所指出的那样,Game类的构造函数出了问题,而不是内存分配本身。
我以为我已经删除了所有可能导致崩溃的东西,但那是在不知道类的成员即使没有明确说明也会被构造的情况下,这导致了崩溃,因为其中一些人以Windows的方式请求文件。
对不起!

相关问题