使用strcat访问内存不良

我正在使用linux .

我有一个叫做的函数:

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]以避免溢出,如果文件的名称太长,如Example cc reference

提前致谢 .

回答(3)

3 years ago

字符串文字(例如 "IntroMusic" )的类型为 const char[N] ,可以隐式转换为 const char * . 通过语言设计中的错误,它也可以转换为 char* ,但该转换在C中被合理地弃用,因此警告 . 您需要使用数组(动态或静态分配),而不是字符串文字 .

或者更好的是,使用 std::string .

3 years ago

首先,“IntroMusic”是const .

从const值中删除const-ness并修改它,是 undefined behaviour . 任何事情都可能发生,你很幸运能立刻得到崩溃 .

此外,为"IntroMusic"分配的内存正好是字符的10个字节加上分隔 \0 ,所以总共11个字节 . 期 . 现在,除了你试图强制修改 const 值之外,你甚至可以写入未分配的内存(至少,你没有为了写入而分配):你只需要尝试将平台相关的文件扩展名写入"IntroMusic"之后的记忆 .

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

Simple solution (因为你标记了问题 c++ ,而不是 c :使用 std::string

3 years ago

看看strcat文档 . 它将目标字符串添加到源字符串 . 在你的情况下,源字符串是“musicFile”,所以它不应该是常量并且应该有足够的长度 .

如果函数被调用如下:

PlayBackgroundIntroMusic((char *)"IntroMusic");

那么musicFile ==“IntroMusic”是不变的,不能被淹没 .