我正在Xamarin Studio开发一款iOS游戏,却遇到了崩溃&;SIGSEGV 。我正在使用AVAudioPlayer播放音效。基本上,我给了一个士兵一种非常非常快的射击能力!在对这种能力进行压力测试时,我遇到了SIGSEGV。我可以在我的项目中成功地复制它。基本上,如果我注释掉所有音效,崩溃就不会发生。如果我让音效播放,崩溃就会发生。
我的项目崩溃了,只给我这个
2014-03-19 18:03:08.304 CyCom[5666:131a3] 18:03:08.303 ERROR: >aqsrv> 65: Exception caught in (null) - error -66634
mono-rt: Stacktrace:
mono-rt: at <unknown> <0xffffffff>
mono-rt: at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff>
mono-rt: at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
mono-rt: at CyCom.Application.Main (string[]) [0x00012] in /Users/jzacherl/Projects/CyCom/CyCom/CyCom/Main.cs:20
mono-rt: at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>
mono-rt:
Native stacktrace:
mono-rt:
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
重要的是要注意,这种崩溃只发生在iOS模拟器上。我无法在iPad设备上重现这种崩溃。这可能是线程计时或垃圾收集,但我只是猜测。我尝试在位于这里的单独项目中复制此,但未成功。我不能让这个崩溃与相同/类似的信息。很明显,我的主要项目和这个测试项目之间有很大的不同(可能是为什么我不能在测试项目中重现它),但我忍不住要动摇这种感觉,即播放声音效果太多/太快导致了这种情况。
这是我演示这个崩溃的视频。在这个视频中,我演示了打开声音,当我发送声音效果时,我最终会因为这个错误而崩溃。然后,我演示了关闭声音效果后,我不会因为这个错误而崩溃。
这里是我的一个播放声音函数的代码片段,以及[a file containing lots of them][3]
public static AVAudioPlayer GetNextAudioPlayer_General( )
{
// The UIApplicationDelegate for the application.
AppDelegate appDel = (AppDelegate)UIApplication.SharedApplication.Delegate;
// The first thing I need to do is take ownership of the next player in the SoundEffectPlayerList. To do this, simply increment the index so no other thread can have this player.
// If this thread is grabbing index 7, and inc the endex, the next thread that trys to access it will get 8... That's why I inc the index ahead of time rather than after.... It's a multi threading bug prevention thing
AVAudioPlayer player = null;
lock(appDel.CyCom.battlefield.SoundEffectPlayerList_General)
{
player = appDel.CyCom.battlefield.SoundEffectPlayerList_General[appDel.CyCom.battlefield.SoundEffectPlayerList_General_Index];
// Inc the index
appDel.CyCom.battlefield.SoundEffectPlayerList_General_Index++;
if ( appDel.CyCom.battlefield.SoundEffectPlayerList_General_Index >= appDel.CyCom.battlefield.SoundEffectPlayerList_General.Count )
{
appDel.CyCom.battlefield.SoundEffectPlayerList_General_Index = 0;
}
}
return player;
}
public static void PlaySoundEffect_FireWeapon ( MySoldier soldier )
{
AppDelegate appDel = (AppDelegate)UIApplication.SharedApplication.Delegate;
// If Audio is enabled and the gamespeed is within limits
if ( appDel.globals.AudioEnabled && appDel.CyCom.GameSpeed <= appDel.globals.Audio_MaxGameSpeedThatAllowsAudioToPlay )
{
// Play Weapon Fire Audio
AVAudioPlayer audioPlayer = Library_Sounds.GetNextAudioPlayer_General();
// Set up the Audio Player with the sound effect to be played
if ( soldier.Attributes.Weapon.WeaponType == appDel.globals.SoldierModelWeaponType_Rifle )
{
audioPlayer = AVAudioPlayer.FromData(appDel.CyCom.SoundEffects.MediaFile_SoundEffects_M4_Fire);
}
else if ( soldier.Attributes.Weapon.WeaponType == appDel.globals.SoldierModelWeaponType_WarheadLauncher )
{
audioPlayer = AVAudioPlayer.FromData(appDel.CyCom.SoundEffects.MediaFile_SoundEffects_Rocket_Launch_01);
}
// Set the volume
audioPlayer.Volume = soldier.PlayerVolume;
audioPlayer.Play();
}
}
关于Rolf的评论:这里是Mac控制台应用程序
的ASI文件链接关于Rolf的评论:这是.crash文件
关于Choper的评论:我替换了每个Player.Play();使用以下代码:
PlayThisAudioPlayer(player);
函数如下:
public static void PlayThisAudioPlayer( AVAudioPlayer player )
{
AppDelegate appDel = (AppDelegate)UIApplication.SharedApplication.Delegate;
player.FinishedPlaying += CreateFinishedPlayingEvent(player);
player.Play();
}
public static EventHandler<AVStatusEventArgs> CreateFinishedPlayingEvent ( AVAudioPlayer player )
{
EventHandler<AVStatusEventArgs> finishedPlayingEvent;
finishedPlayingEvent = delegate(object sender, AVStatusEventArgs e) {
player.Stop();
player.FinishedPlaying -= finishedPlayingEvent;
player.Dispose();
player = null;
};
return finishedPlayingEvent;
}
我现在遇到这个崩溃:
2014-03-20 11:09:37.568 CyCom[5533:a0b] EXCEPTION IN THE MAIN.CS
2014-03-20 11:09:37.569 CyCom[5533:a0b] the player object was Dispose()d during the callback, this has corrupted the state of the program
2014-03-20 11:09:37.569 CyCom[5533:a0b] at MonoTouch.AVFoundation.InternalAVAudioPlayerDelegate.FinishedPlaying (MonoTouch.AVFoundation.AVAudioPlayer player, Boolean flag) [0x00032] in /Developer/MonoTouch/Source/maccore/src/AVFoundation/Events.cs:72
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
at CyCom.Application.Main (System.String[] args) [0x00013] in /Users/jzacherl/Projects/CyCom/CyCom/CyCom/Main.cs:23
附加虽然:我认为问题可能是我使用静态函数....试着证明这是真的还是假的。
我给了Choper这里的复选标记,因为问题最终是我重用avaudioplayer,而不是处理它们。无论出于何种原因,您都不能长时间连续重复使用avaudioplayer。我不知道为什么,但事实证明这是不好的!我重新设计了我的代码,这样AVAudio播放器是在需要的时候创建的,然后由后台线程处理。
添加到您的代码中:
audioPlayer.FinishedPlaying += HandleAudioFinished;
...
private void HandleAudioFinished (object sender, AVStatusEventArgs e)
{
if (audioPlayer != null)
{
audioPlayer.Stop();
audioPlayer.FinishedPlaying -= HandleAudioFinished;
audioPlayer.Dispose();
audioPlayer = null;
}
}