Well, after trying for a while...exceptions do still occur. The message "AL lib: (EE) alc_cleanup: 1 device not closed" does not appear but there are exceptions if you close the window just when the ball is hitting and emitting its sound.
This is the code to reproduce the issue:
1. Create a new console app (.NET 5) in VSC2019.
2. Add SFML.NET nuget package to your project.
3. Add some ballHitSound.wav sample into you project's folder. You can find many sounds here:
https://www.epidemicsound.com/sound-effects/search/?term=ball%20hit?term=ball%20hit. For instance "Ping Pong Ball Hit 4", i think that is the same as I am using.
4. Copy paste this code:
using SFML.Audio;using SFML.Graphics;using SFML.System;using SFML.Window;using System;namespace MovingBall
{ class Program
{ const int WINDOW_WIDTH
= 50; const int WINDOW_HEIGHT
= 50; static void Main
(string[] args
) { Game pg
= new Game
(WINDOW_WIDTH, WINDOW_HEIGHT,
"Bouncing ball example"); // Create a moving ball Random rand
= new Random
(1); float radius
= 20
.0f
;// rand.Next(5, 30); Vector2f velocity
= new Vector2f
(rand
.Next(100,
1000), rand
.Next(100,
1000)); pg
.CreateBall(radius, velocity
); pg
.Run(); } } class Game
{ public string Title
{ get; set; } public VideoMode VideoMode
{ get; set; } public RenderWindow Window
{ get; set; } public Ball Ball
{ get; set; } /// <summary> /// Create a game with empty window /// </summary> public Game
(uint windowWidth,
uint windowHeight,
string title
) { Title
= title
; VideoMode
= new VideoMode
(windowWidth, windowHeight
); Window
= new RenderWindow
(VideoMode, Title, Styles
.Close); // Comment/uncomment does not matter, the issue happens either way //Window.SetVerticalSyncEnabled(true); //Window.SetFramerateLimit(60); Window
.Closed += Window_Closed
; Window
.KeyPressed += Window_KeyPressed
; } public void CreateBall
(float radius, Vector2f velocity
) { Ball
= new Ball
(radius, velocity, Window
.Size.X, Window
.Size.Y); } /* Window events */ private void Window_Closed
(object sender, EventArgs e
) { // The exception occurs no matter the order of disposing... Ball
.SoundBuffer.Dispose(); Ball
.Sound.Dispose(); (sender
as RenderWindow
).Close(); } private void Window_KeyPressed
(object sender, KeyEventArgs e
) { if (e
.Code == Keyboard
.Key.Escape) { (sender
as RenderWindow
).Close(); } } /* Main loop */ public void Run
() { Clock clock
= new Clock
(); Time delta
= Time
.Zero; while (Window
.IsOpen) { // EVENTS // Check now all events (e.g., window close) Window
.DispatchEvents(); // Get elapsed time since last frame delta
= clock
.Restart(); // UPDATE (positions, etc.) Ball
.Update(delta, Window
.Size.X, Window
.Size.Y); // DRAW ELEMENTS Window
.Clear(); Window
.Draw(Ball
.Shape); // DISPLAY Window
.Display(); } } } class Ball
{ private uint _pointCount
= 100; public CircleShape Shape
{ get; set; } public Vector2f Velocity
{ get; set; } public Sound Sound
{ get; set; } public SoundBuffer SoundBuffer
{ get; set; } public Ball
(float radius, Vector2f velocity,
uint windowWidth,
uint windowHeight
) { // Shape Shape
= new CircleShape
(radius, _pointCount
); Shape
.FillColor = Color
.Red; // Sound (when hits something) SoundBuffer
= new SoundBuffer
("../../../ballHitSound.wav"); Sound
= new Sound
(SoundBuffer
); // Set origin to its center Shape
.Origin = new Vector2f
(Shape
.GetLocalBounds().Width / 2
.0f, Shape
.GetLocalBounds().Height / 2
.0f
); // Set initial position to center of the window Shape
.Position = new Vector2f
(windowWidth
/ 2
.0f, windowHeight
/ 2
.0f
); // Set speed Velocity
= velocity
; } public void Update
(Time delta,
uint windowWidth,
uint windowHeight
) { // Get current location borders of the ball // (Top-left, Top-right, top-top, top-bottom) float left
= Shape
.Position.X - Shape
.Radius; float right
= Shape
.Position.X + Shape
.Radius; float top
= Shape
.Position.Y - Shape
.Radius; float bottom
= Shape
.Position.Y + Shape
.Radius; // Check if current ball's boundaries are out of window's limits // If that is the case, change sign of speed and play the hit sound if ((left
<= 0 && Velocity
.X < 0) || (right
>= windowWidth
&& Velocity
.X > 0)) { Velocity
= new Vector2f
(Velocity
.X * -1, Velocity
.Y); Sound
.Play(); } if ((top
<= 0 && Velocity
.Y < 0) || (bottom
>= windowHeight
&& Velocity
.Y > 0)) { Velocity
= new Vector2f
(Velocity
.X, Velocity
.Y * -1); Sound
.Play(); } // Move Shape
.Position += new Vector2f
(delta
.AsSeconds() * Velocity
.X, delta
.AsSeconds() * Velocity
.Y); } }} Now, you can try to get the issue by closing the window just when the ball hits the walls. The easiest way is of course using a ball larger than the window size (so the hitting sound is happening at a very high frequency and the exception
"System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'" will happen always.
In console window the error shown is:
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
at SFML.Audio.Sound.sfSound_play(IntPtr)
--------------------------------
at SFML.Audio.Sound.Play()
at MovingBall.Ball.Update(SFML.System.Time, UInt32, UInt32)
at MovingBall.Game.Run()
at MovingBall.Program.Main(System.String[])
I may try the same in C++ and see what happens.