从导致 AccessViolationException 的线程访问文件缓冲区

Posted

技术标签:

【中文标题】从导致 AccessViolationException 的线程访问文件缓冲区【英文标题】:Access File buffer from a Thread Causing AccessViolationException 【发布时间】:2015-03-19 04:37:31 【问题描述】:

我有一些想要从线程中播放的 wav 声音。我在程序启动时将声音加载到内存中,然后使用 Windows 函数 PlaySound 播放它们。这可行,但是当我尝试从线程播放声音时,我得到一个 AccessViolationException,“尝试读取或写入受保护的内存”。

有没有办法将文件加载到 char 数组中,然后从单独的线程中读取?

这是我用来加载和播放声音文件的代码。

// Code to load sound from file into char*.
    ifstream ifs(WaveSounds::sounds::StartupMusic, ios::binary | ios::ate);
	// The ios::ate flag sets the filestream
	// to the end position, so it's already
	// ata the end when we call 'tellg()'.
	if (&std::ios::ios_base::good)
			
		int length = ifs.tellg();
		ifs.seekg(0, ifs.beg);
		// Load into the Char * , 'n_StartMusic'.
		n_StartMusic = new char[length];
		ifs.read(n_StartMusic, length);
		ifs.close();
	

// Plays sound from thread, causes AccessViolationException.
static void PlaySoundThread()
		
	PlaySound((LPWSTR)WaveSounds::n_CurSound, NULL, SND_MEMORY | SND_ASYNC);


// Method that sets sound to play and starts thread.
void WaveSounds::Play_Sound(char* sound)
		
	n_CurSound = sound;
	n_hmod = GetModuleHandle(0);
	Thread^ t = gcnew Thread(gcnew ThreadStart(PlaySoundThread));
	t->IsBackground = true;
	t->Start();	

【问题讨论】:

【参考方案1】:

如果 char* 声音通过 wave.play_sound(&c); 传入堆栈中的函数;到线程启动时 c 可能已被删除,因此 m_nCurSound 指向已清除的内存。

要修复此更改,将 m_nCurSound=sound 更改为 m_nCurSound= new char[255]; strcpy(声音, m_nCurSound);

【讨论】:

是的,就是这样。该文件在类的初始化程序中加载,但我通过在调用它的同一个函数中声明该类的实例来测试它,因此它将它加载到堆栈而不是堆中。当我声明一个单独的类实例然后尝试它时,它工作得很好。菜鸟错误,因为我还是 C++ 新手。谢谢!

以上是关于从导致 AccessViolationException 的线程访问文件缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

从 nib 实例化 UIView 导致无限循环问题

UIViewAnimation 导致从枚举类型隐式转换

MSMQ:从队列接收时,啥会导致“资源不足以执行操作”错误?

什么可能导致从 Windows 服务执行的进程运行比从命令行(管理员)运行慢?

从数组复制到变量导致***

为啥从 WM_NCPAINT 使用 DrawImageUnscaled 会导致闪烁?