提问者:小点点

使用strcat对内存的访问错误


我在用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个答案

匿名用户

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

或者使用std::string更好。

匿名用户

首先,“Intromusic”是常量。

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

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

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

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

匿名用户

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

如果函数是这样调用的:

PlayBackgroundIntroMusic((char *)"IntroMusic");

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