gpt4 book ai didi

android - 在 NDK 中使用 fopen()、fread() 打开文件时出现致命信号 11,但 AAsset_read 工作正常

转载 作者:太空宇宙 更新时间:2023-11-04 03:55:18 27 4
gpt4 key购买 nike

我正在尝试从 SD 卡读取 wav 文件,用于我正在使用 NDK 和 100% native 代码构建的音频采样器应用程序。我有一种方法可以遍历包含样本路径的预定义数组,并将每个样本路径单独流式传输到数据缓冲区中,以便稍后由 OpenSL 播放。

当我将文件作为 Assets 加载时,使用以下方法:

int open_asset(AAssetManager* mgr, char* filename, int samp)
{

assert(NULL != mgr);
AAsset *asset = AAssetManager_open(mgr, filename, AASSET_MODE_BUFFER);

__android_log_write(ANDROID_LOG_DEBUG, "ASSET", "AAssetManager_open");

if (NULL == asset)
{
__android_log_write(ANDROID_LOG_DEBUG, "ASSET", "Asset not found, loading aborted.");
return JNI_FALSE;
}

oneshot_samples[samp].buffer_header = (unsigned short*) malloc(HEADER_SIZE);
AAsset_read(asset, oneshot_samples[samp].buffer_header, HEADER_SIZE);

unsigned short* fmttype;
unsigned long* databytes;

fmttype = (oneshot_samples[samp].buffer_header + 10);

if (*fmttype != 0x1)
{
__android_log_write(ANDROID_LOG_DEBUG, "ASSET", "*fmttype not PCM, loading aborted.");
return JNI_FALSE;
}

databytes = (oneshot_samples[samp].buffer_header + 20);

oneshot_samples[samp].data_size = *databytes;

oneshot_samples[samp].buffer_data = (unsigned short*) malloc(*databytes);
AAsset_seek(asset, HEADER_SIZE, SEEK_SET);
AAsset_read(asset, oneshot_samples[samp].buffer_data, oneshot_samples[samp].data_size);

__android_log_print(ANDROID_LOG_DEBUG, "ASSET", "*fmttype: %x", *fmttype);
__android_log_print(ANDROID_LOG_DEBUG, "ASSET", "*databytes: %x", *databytes);

AAsset_close(asset);

__android_log_write(ANDROID_LOG_DEBUG, "ASSET", "AAsset_close(asset)");

return JNI_TRUE;
}

它们加载没有问题。但是对于我的应用程序,我希望用户也能够从 SD 卡中读取样本。我将文件路径更改为 SD 卡上的硬编码位置(仅用于测试),并使用 fopen() 和 fread() 尝试了以下方法:

void open_external_file(char* filepath, int samp)
{

FILE* fp;
oneshot_samples[samp].buffer_header = (unsigned short*) malloc(HEADER_SIZE);

__android_log_print(ANDROID_LOG_DEBUG, "open_external_file",
"filepath: %s", filepath);

__android_log_print(ANDROID_LOG_DEBUG, "open_external_file",
"size of filepath: %d", sizeof filepath);

if ((fp = fopen(filepath, "r")) != NULL)
{
__android_log_write(ANDROID_LOG_DEBUG, "open_external_file", "fopen()");

fread(oneshot_samples[samp].buffer_header, sizeof(unsigned short), HEADER_SIZE, fp);
}

unsigned short* fmttype;
unsigned long* databytes;

fmttype = (oneshot_samples[samp].buffer_header + 10);

if (*fmttype != 0x1)
{
__android_log_write(ANDROID_LOG_DEBUG, "open_external_file", "*fmttype not PCM, loading aborted.");
}

databytes = (oneshot_samples[samp].buffer_header + 20);
oneshot_samples[samp].data_size = *databytes;
oneshot_samples[samp].buffer_data = (unsigned short*) malloc(*databytes);

__android_log_print(ANDROID_LOG_DEBUG, "open_external_file", "*fmttype: %x", *fmttype);
__android_log_print(ANDROID_LOG_DEBUG, "open_external_file", "*databytes: %x", *databytes);


fseek(fp , HEADER_SIZE , SEEK_SET);
fread(oneshot_samples[samp].buffer_data, sizeof(unsigned short), oneshot_samples[samp].data_size, fp);

fclose(fp);
__android_log_write(ANDROID_LOG_DEBUG, "open_external_file", "fclose(fp);");
}

这给了我可怕的 ANR 和不可避免的崩溃:

06-06 11:42:30.915: I/dalvikvm(7222): threadid=3: reacting to signal 3 06-06 11:42:30.915: A/libc(7222): Fatal signal 11 (SIGSEGV) at 0x0000000c (code=1)

但奇怪的是,它似乎是随机发生的——有 36 个奇数样本,有时错误出现在第 4 个之后,有时在 20 个左右之后。看完这篇thread ,它似乎可能是一个段错误,但我不知道它是如何引起的——或者这两种方法之间的区别是什么。

文件头 *fmttype 和 *databytes 的值每次都 100% 正确返回。

我是 C 的新手,所以我很可能做错了一些明显错误的事情 - 如果更有经验的人能够阐明可能的原因,我将不胜感激。

更新:我使用 AAsset_read() 切换回来,但仍然得到:

06-06 12:33:50.393: I/dalvikvm(9755): threadid=3: reacting to signal 3 06-06 12:33:50.393: I/dalvikvm(9755): Wrote stack traces to '/data/anr/traces.txt'

但文件每次仍能正常加载,应用程序也不会崩溃。对于 512 MB 的测试平板电脑,我的测试样本的总大小为 48.4 MB - 这会导致问题吗?不过,如果是的话,我看不出使用 AAsset_read() 会有什么不同。

最佳答案

您正在分配 HEADER_SIZE字节数:

(unsigned short*) malloc(HEADER_SIZE);

然后阅读HEADER_SIZE * 2字节进入其中,溢出缓冲区:

fread(oneshot_samples[samp].buffer_header, sizeof(unsigned short), HEADER_SIZE, fp);

( fread() 乘以 sizeof(unsigned short) ,加倍。)

您再次对 HEADER_SIZE 进行相同的过度阅读. android Assets 实现不会失败,因为您正在读取正确数量的数据。通过更改 databytes 修复它。至 sizeof(unsigned short) .

无关:如果 fopen() 返回 NULL,您可能应该从函数返回,而不是处理未初始化的数据。

“信号 3”消息仅表示系统正在请求应用程序的堆栈跟踪,可能是因为主线程很忙并且没有响应消息。

关于android - 在 NDK 中使用 fopen()、fread() 打开文件时出现致命信号 11,但 AAsset_read 工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16951680/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com