当前位置: 首页 > 知识库问答 >
问题:

使用strcat对内存的访问错误

诸葛乐逸
2023-03-14

我在用Linux。

我有一个函数叫like:

PlayBackgroundIntroMusic((char *)"IntroMusic");

功能是:

void SoundManager::
PlayBackgroundIntroMusic( char * musicFile)
{
        // Concatenate extension for each platform
        strcat (musicFile,audioExtension);
        CCLOG("musicFile: %c" musicFile);
  SimpleAudioEngine::sharedEngine()->playBackgroundMusic(std::string(CCFileUtils::fullPathFromRelativePath(musicFile)).c_str(), false);
}

但我无法访问在线内存:

strcat (musicFile,audioExtension);

声明audioExtension:

#include 
using std::string;
#include 
using std::cout; using std::cerr; using std::endl;

/**
 * Declare sound extension for each platform
 * Android = ogg
 * iOS = caf
 * WIN32 = mp3
 */

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
        static const char * audioExtension = ".wav";
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
        static const char * audioExtension = ".caf";
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
        static const char * audioExtension = ".ogg";
#endif

所以,我希望有:

IntroMusic.caf on iOS
IntroMusic.ogg on Android

发生什么事了?

注意:我已尝试:

 char * musicFileWithExtension = strcat (musicFile,audioExtension);

但无论如何都没用。

musicFile不是常量。我不想声明一个tempchar[80]以避免文件名太长时溢出,如示例cc引用

提前道谢。

共有3个答案

柴彬
2023-03-14

查看strcat文档。它正在将目标字符串添加到源字符串中。在您的示例中,源字符串是“musicfile”,因此它不应该是常量,并且应该有足够的长度。

如果函数是这样调用的:

PlayBackgroundIntroMusic((char *)"IntroMusic");

则musicFile==“intromusic”为常量,不能覆盖。

闻人弘雅
2023-03-14

首先,“Intromusic”是常量。

从常量值中删除常量并修改它是未定义的行为。任何事情都有可能发生,你很幸运马上就被撞车了。

此外,为“IntroMusic”分配的内存正好是10个字节的字符加上一个限定符\0,因此总共是11个字节。句号。现在,除了尝试强制修改const值之外,您甚至会写入未分配的内存(至少,不是您为写入该内存而分配的):您只需尝试将与平台相关的文件扩展名写入“intromusic”之后的内存。

您有责任为您的操作提供足够大的缓冲区。

简单的解决方案(由于您将问题标记为C++,而不是C:使用std::string

臧友樵
2023-03-14

字符串文字(如“intromusic”)的类型为const char[N],可隐式转换为const char*。由于语言设计中的一个错误,它也可以转换为char*,但这种转换在C++中是正确的,因此提出了警告。您需要使用数组(动态或静态分配),而不是字符串文字。

或者使用std::string更好。

 类似资料:
  • 我正在使用tess4j.jar编写一个程序。该程序正在从图像中提取文本及其位置。我得到这个错误: 有趣的是,它不会出现在每张图片上。有人知道我哪里出错了吗? 这是我的代码:

  • 问题内容: 我出于好奇而学习x86汇编。我目前正在使用带有NASM汇编器的基于Linux的操作系统。我很难理解为什么 会导致分段错误(将ebx寄存器的内容移至内存位置0xFFF时)。我当时以为在纯asm中构建程序将使我能够不受限制地访问进程的虚拟地址空间。不是吗? 您将如何在程序集中实现类似堆的内容? 问题答案: 在Linux(x86)上-尽管您的进程中的虚拟地址范围为4gb,但并非所有虚拟地址都

  • 例子 a.c: #include <stdio.h> int main(void) { // your code goes here int a[3] = {0}; a[3] = 1; printf("%d\n", a[3]); return 0; } b.c: #include <stdio.h> #inclu

  • 问题内容: 我正在开发一个宠物的开源项目,该项目实现了一些流密码算法,并且只有在ARM处理器上运行该bug时,我才遇到问题。我什至尝试在qemu下的x86中运行ARM二进制文件,但该错误并未在那里触发。 该错误的具体机制仍然难以捉摸,但是我最好的选择是相信它是由程序中未对齐的内存访问尝试引起的,这是qemu实现的,但被开发板中的真正ARM处理器默默忽略了。 因此,由于该问题很难诊断,所以我想知道是

  • 我试图通过使用预取来加速单个程序。我的程序的目的只是为了测试。以下是它的作用: 它使用两个大小相同的int缓冲区 第一次,第一个缓冲区中的值包含其索引的值(参见下面代码中的函数)。 在我的程序代码中会更清楚: 如果我启动它,我得到以下输出: 快,快!!!据我所知(我可能错了),有这么快的程序的原因之一是,当我依次访问我的两个缓冲区时,数据可以在CPU缓存中预取。 我们可以使它更复杂,以便数据(几乎

  • 问题内容: 在这篇“ 接口Linux信号”文章之后,我一直试图在 amd64中* 使用,但是在发送信号时总是会遇到 内存访问错误 。使用 C / C ++ 函数时, struct sigaction 有效。 * 通话有什么问题? 具有ASM代码的C / C ++: 编译 发送信号 问题答案: 在x86-64 linux中,必须提供a,而您尚未提供。 内核源码的相关部分: 在C库包装为您完成此: 使