C语言 在x86(Android API30、API31)上不会发生Android x86_64上的崩溃

mmvthczy  于 2023-01-16  发布在  Android
关注(0)|答案(1)|浏览(146)

原标题为:vsprintf从Android12开始崩溃(api〉= 31)
我的Android应用使用NDK构建的本机库(libexif)。在我的本机代码(改编自exif)中的某个时候,我调用了vsprintf函数,导致应用崩溃。以前在exif中,它是对vfprintf (stderr, format, args);的调用,我将其替换为vsprintf,以便存储字符串供以后使用。

static void
log_func (ExifLog *log, ExifLogCode code, const char *domain,
          const char *format, va_list args, void *data)
{
  char dest[1024] = {0, };
  vsprintf(dest, format, args);
}

消息(根据其工作的API的输出)应为:

The tag 'ComponentsConfiguration' contains an invalid number of components (3, expected 4).

format变量包含:"The tag '%s' contains an invalid number of components (%i, expected %i)."
我无法检查参数的值(还没有找到如何打印它们来检查它们的值)。
这在API30(在模拟器上)之前没有任何问题。在使用API31的映像上,它在调用vsprintf函数时崩溃。
更新NDK到25b也不能修复。我的API30映像是x86,API31映像是x86_64。

    • 是否有解决/解决此问题的方法?**

可能感兴趣的其他代码部分:

#ifndef NO_VERBOSE_TAG_STRINGS
static void
exif_entry_log (ExifEntry *e, ExifLogCode code, const char *format, ...)
{
    va_list args;
    ExifLog *l = NULL;

    if (e && e->parent && e->parent->parent)
        l = exif_data_get_log (e->parent->parent);
    va_start (args, format);
    exif_logv (l, code, "ExifEntry", format, args);
    va_end (args);
}
#else
#if defined(__STDC_VERSION__) &&  __STDC_VERSION__ >= 199901L
#define exif_entry_log(...) do { } while (0)
#elif defined(__GNUC__)
#define exif_entry_log(x...) do { } while (0)
#else
#define exif_entry_log (void)
#endif
#endif

#define CC(entry,target,v,maxlen)                   \
{                                   \
    if (entry->components != target) {              \
        exif_entry_log (entry, EXIF_LOG_CODE_CORRUPT_DATA,  \
            _("The tag '%s' contains an invalid number of " \
              "components (%i, expected %i)."),     \
            exif_tag_get_name (entry->tag),     \
            (int) entry->components, (int) target);     \
        break;                          \
    }                               \
}

// Then this call later

  CC (e, 4, val, maxlen);

更新:

  • 同时,由于API30映像具有x86架构,而API31映像是x86_64,我刚刚尝试了API30与x86_64。
  • API 30 x86 →应用程序崩溃
  • API 30 x86_64 →应用程序崩溃
  • API 31 x86_64 →应用程序崩溃

因此,这看起来像是x86与x86_64模拟器映像相关。

  • 在真正的arm8设备上,也没有崩溃。
  • 我还发现传递给vsprintf的参数没有预期的值。如果用预期的值模拟vsprintfvsprintf工作正常。所以问题可能不是vsprintf
xdyibdwo

xdyibdwo1#

问题的原因是我使用了两次args:一次在vsprintf,一次在vsprintf
根据https://stackoverflow.com/a/10807375/15401262,这现在是允许的,并导致未定义的行为。
它不能使用两次,在这种情况下必须使用va_copy。

相关问题