[英]SDL2 - Visual Studio 2017 SDL_FreeWAV Access Violation
I'm using SDL2, and created an Audio
class to handle game music and sound effects. 我正在使用SDL2,并创建了一个
Audio
类来处理游戏音乐和声音效果。 The sound works perfectly, but whenever the Audio
class is destructed, the SDL_FreeWAV()
call throws an access violation: 声音效果完美,但是只要销毁
Audio
类, SDL_FreeWAV()
调用就会引发访问冲突:
Exception thrown at 0x000000006C7A8737 (SDL2.dll) in Program.exe: 0xC0000005: Access violation reading location 0x00007FF4A9080008
在Program.exe中的0x000000006C7A8737(SDL2.dll)处引发异常:0xC0000005:访问冲突读取位置0x00007FF4A9080008
Audio.h: Audio.h:
#pragma once
namespace Audio {
class Audio {
public:
Audio ();
Audio (char*, char*);
~Audio ();
void pause (int);
private:
Uint32 wav_length;
Uint8 *wav_buffer = NULL;
SDL_AudioSpec wav_spec;
SDL_AudioDeviceID device_id;
int success;
};
class Music {
public:
Music ();
Music (char*);
~Music ();
private:
Audio *audio = NULL;
};
class Effect {
public:
Effect ();
Effect (char*);
~Effect ();
private:
};
};
Audio.cpp Audio.cpp
#include "stdafx.h"
#include "Audio.h"
#include "SDL_audio.h"
namespace Audio {
Audio::Audio () {
//Default constructor
}
Audio::Audio (char *filename, char *channelName) {
if (SDL_LoadWAV (filename, &this->wav_spec, &this->wav_buffer, &this->wav_length) == NULL) {
std::cout << "[-] SDL: " << SDL_GetError () << "\n";
exit (ERROR_SDL_AUDIO_WAV_LOAD);
}
this->device_id = SDL_OpenAudioDevice (channelName, 0, &this->wav_spec, NULL, 0);
this->success = SDL_QueueAudio (this->device_id, this->wav_buffer, this->wav_length);
}
Audio::~Audio () {
SDL_CloseAudioDevice (this->device_id);
SDL_FreeWAV (this->wav_buffer); // <-- access violation here
}
void Audio::pause (int on) {
SDL_PauseAudioDevice (this->device_id, on);
}
};
As long as you have a default constructor and didn't define your own, the C++ compiler gives you a move constructor
and a copy constructor
for free. 只要您具有默认构造函数且未定义自己的构造函数,C ++编译器就会为您免费提供
move constructor
和copy constructor
。 They shallow-copy all members of the object. 他们浅拷贝对象的所有成员。
When you use operator=
(assignment of the object to another object), it uses the copy
constructor. 当您使用
operator=
(将对象分配给另一个对象)时,它将使用copy
构造函数。 When you return a temporary object (rvalue), it uses the move
constructor. 当您返回一个临时对象(右值)时,它将使用
move
构造函数。
Sadly the default copy and move constructors don't fit you in this case. 遗憾的是,在这种情况下,默认的复制和移动构造函数不适合您。
Consider this: 考虑一下:
Audio a = Audio("filename", "channel");
In this deceptively simple line of code you're: 在这看似简单的代码行中,您是:
Audio
object Audio
对象 Audio::operator=
Audio::operator=
move constructor
move constructor
So after this line of valid C++, a
has: 因此,在这行有效的C ++之后,
a
具有:
device_id
that was closed. device_id
。 wav_buffer
that was freed. wav_buffer
。 So how do we fix this? 那么我们该如何解决呢?
Audio::Audio (char *filename, char *channelName) {
if (SDL_LoadWAV (filename, &this->wav_spec, &this->wav_buffer, &this->wav_length) == NULL) {
std::cout << "[-] SDL: " << SDL_GetError () << "\n";
exit (ERROR_SDL_AUDIO_WAV_LOAD);
}
this->device_id = SDL_OpenAudioDevice (channelName, 0, &this->wav_spec, NULL, 0);
this->success = SDL_QueueAudio (this->device_id, this->wav_buffer, this->wav_length);
}
Audio::Audio(Audio&& other) : // move constructor
wav_length(other.wav_length),
wav_buffer(other.wav_buffer),
wav_spec(other.wav_spec),
device_id(other.device_id),
success(other.success)
{
other.wav_buffer = nullptr;
}
Audio::~Audio () {
if(wav_buffer != nullptr) {
SDL_CloseAudioDevice (this->device_id);
SDL_FreeWAV (this->wav_buffer); // Gives access violation
}
}
Now when an Audio
object is moved, its wav_buffer
is nullified so that it won't be cleaned up when it's destroyed. 现在,当移动
Audio
对象时,其wav_buffer
会无效,以便销毁它时不会对其进行清理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.