Anonim

AIMBOT 2.0

Dalam episod 1 Permainan Baru 2, sekitar jam 9:40, terdapat gambaran mengenai kod yang telah ditulis oleh Nene:

Inilah dia dalam bentuk teks dengan komen yang diterjemahkan:

// the calculation of damage when attacked void DestructibleActor::ReceiveDamage(float sourceDamage) { // apply debuffs auto resolvedDamage = sourceDamage; for (const auto& debuf:m_debufs) { resolvedDamage = debuf.ApplyToDamage(resolvedDamage); m_currentHealth -= resolvedDamage if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); } } } 

Setelah tembakan, Umiko, menunjuk ke arah gelung, mengatakan bahawa sebab mengapa kod itu jatuh adalah kerana terdapat gelung tak terhingga.

Saya tidak begitu mengenali C ++ jadi saya tidak pasti sama ada apa yang dia katakan itu benar.

Dari apa yang saya dapat lihat, loop for is iterate melalui debuf yang dimiliki oleh Pelakon pada masa ini. Kecuali Pelakon mempunyai debuf yang tidak terbatas, saya rasa ia tidak boleh menjadi gelung tanpa batas.

Tetapi saya tidak pasti kerana satu-satunya alasan bahawa terdapat banyak kod adalah mereka ingin meletakkan telur paskah di sini, bukan? Kami hanya akan mendapat bahagian belakang komputer riba dan mendengar Umiko berkata "Oh, anda mempunyai gelung tanpa batas di sana". Fakta bahawa mereka benar-benar menunjukkan beberapa kod membuat saya berfikir bahawa entah bagaimana kod itu adalah telur paskah dari beberapa jenis.

Adakah kod itu benar-benar akan membuat gelung tanpa batas?

8
  • Mungkin bermanfaat: tangkapan skrin tambahan Umiko yang mengatakan bahawa "Itu memanggil operasi yang sama berulang-ulang kali ", yang mungkin tidak ditunjukkan dalam kod.
  • Oh! Saya tidak tahu itu! @AkiTanaka sub yang saya tonton mengatakan "gelung tak terhingga"
  • @LoganM Saya tidak begitu setuju. Bukan hanya OP mempunyai pertanyaan mengenai beberapa kod sumber yang kebetulan berasal dari anime; Soalan OP adalah mengenai pernyataan tertentu yang dibuat mengenai kod sumber oleh watak dalam anime, dan ada jawapan yang berkaitan dengan anime, iaitu "Crunchyroll dilakukan dengan cara yang salah dan tidak diterjemahkan barisnya".
  • @senshin Saya rasa anda membaca soalan yang anda mahukan, bukannya soalan yang sebenarnya diajukan. Soalan itu memberikan beberapa kod sumber dan bertanya sama ada ia menghasilkan gelung tak terhingga sebagai kod C ++ kehidupan sebenar. Permainan baru! adalah karya rekaan; tidak perlu ada kod yang disajikan di dalamnya untuk mematuhi standard kehidupan sebenar. Apa yang Umiko katakan mengenai kodnya lebih berwibawa daripada piawaian atau penyusun C ++ mana pun. Jawapan teratas (diterima) tidak menyebutkan maklumat dalam alam semesta. Saya rasa soalan di atas topik boleh diajukan mengenai ini dengan jawapan yang baik, tetapi seperti yang diungkapkan, bukan.

Kod ini bukan gelung tanpa batas tetapi bug.

Terdapat dua (mungkin tiga) masalah:

  • Sekiranya tidak ada debuf, kerosakan tidak akan berlaku sama sekali
  • Kerosakan berlebihan akan berlaku sekiranya terdapat lebih dari 1 debuf
  • Sekiranya DestroyMe () segera menghapus objek dan masih ada m_debuf yang akan diproses, gelung akan dijalankan di atas objek yang dihapus dan memori sampah. Sebilangan besar enjin permainan mempunyai barisan kehancuran untuk mengatasi masalah ini dan lebih-lebih lagi yang mungkin tidak menjadi masalah.

Permohonan kerosakan harus berada di luar gelung.

Inilah fungsi yang diperbetulkan:

// the calculation of damage when attacked void DestructibleActor::ReceiveDamage(float sourceDamage) { // apply debuffs auto resolvedDamage = sourceDamage; for (const auto& debuf:m_debufs) { resolvedDamage = debuf.ApplyToDamage(resolvedDamage); } m_currentHealth -= resolvedDamage if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); } } 
12
  • 15 Adakah kita dalam Kajian Kod? : D
  • 4 apungan sangat bagus untuk kesihatan jika anda tidak melebihi 16777216 HP. Anda bahkan boleh menetapkan kesihatan menjadi tak terbatas untuk membuat musuh yang anda boleh tewas tetapi tidak akan mati, dan melakukan serangan satu-satu dengan menggunakan kerosakan tanpa batas yang masih tidak akan membunuh watak HP yang tidak terhingga (hasil INF-INF adalah NaN) tetapi akan membunuh semua yang lain. Oleh itu, ia sangat berguna.
  • 1 @ cat Secara konvensional dalam banyak standard pengkodan m_ awalan bermaksud pemboleh ubah anggota. Dalam kes ini pemboleh ubah anggota dari DestructibleActor.
  • 2 @HotelCalifornia Saya setuju ada peluang kecil ApplyToDamage tidak berfungsi seperti yang diharapkan tetapi dalam kes contoh yang anda berikan saya akan katakan ApplyToDamage juga perlu dikerjakan semula untuk mewajibkan menyebarkannya yang asli sourceDamage juga sehingga dapat mengira debuf dengan betul dalam kes-kes tersebut. Untuk menjadi pedant mutlak: pada ketika ini maklumat dmg mestilah struktur yang merangkumi dmg asal, dmg semasa, dan sifat kerosakan juga jika debuf mempunyai perkara seperti "kerentanan terhadap kebakaran". Dari pengalaman tidak lama sebelum reka bentuk permainan dengan debuf menuntut ini.
  • 1 @StephaneHockenhull betul!

Kod tersebut nampaknya tidak membuat gelung tanpa batas.

Satu-satunya cara gelung tidak terbatas adalah jika

debuf.ApplyToDamage(resolvedDamage); 

atau

DestroyMe(); 

untuk menambah item baru ke m_debufs bekas.

Ini nampaknya tidak mungkin. Dan jika memang demikian, program tersebut dapat terhenti kerana menukar wadah semasa diulang.

Program ini kemungkinan besar akan terhenti kerana panggilan ke DestroyMe(); yang mungkin menghancurkan objek semasa yang sedang menjalankan gelung.

Kita boleh menganggapnya sebagai kartun di mana 'orang jahat' melihat cabang untuk menjadikan 'lelaki baik' jatuh, tetapi menyedari terlambat bahawa dia berada di sisi yang salah. Atau Ular Midgaard memakan ekornya sendiri.


Saya juga harus menambah bahawa gejala yang paling biasa dari gelung tak terhingga adalah bahawa ia membekukan program atau menjadikannya tidak responsif. Ia akan merosakkan program jika mengalokasikan memori berulang kali, atau melakukan sesuatu yang akhirnya dibahagi dengan sifar, atau yang serupa.


Berdasarkan komen oleh Aki Tanaka,

Mungkin bermanfaat: tangkapan skrin tambahan Umiko yang mengatakan bahawa "Ia memanggil operasi yang sama berulang kali", yang mungkin tidak ditunjukkan dalam kod.

"Ia memanggil operasi yang sama berulang kali" Ini lebih mungkin.

Dengan andaian bahawa DestroyMe(); tidak dirancang untuk dipanggil lebih dari sekali, lebih cenderung menyebabkan kemalangan.

Cara untuk menyelesaikan masalah ini adalah dengan menukar if untuk perkara seperti ini:

 if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); break; } 

Ini akan keluar dari gelung ketika DestructibleActor dimusnahkan, memastikan bahawa 1) DestroyMe kaedah dipanggil hanya sekali dan 2) jangan gunakan buff tidak berguna apabila objek sudah dianggap mati.

2
  • 1 Putus keluar dari gelung ketika kesihatan <= 0 jelas merupakan kaedah yang lebih baik daripada menunggu sehingga selepas gelung untuk memeriksa kesihatan.
  • Saya rasa mungkin break keluar dari gelung, dan kemudian panggil DestroyMe(), hanya untuk selamat

Terdapat beberapa masalah dengan kod:

  1. Sekiranya tidak ada debuf, kerosakan tidak akan ditanggung.
  2. DestroyMe() nama fungsi terdengar berbahaya. Bergantung pada bagaimana pelaksanaannya, mungkin atau tidak menjadi masalah. Sekiranya ia hanya panggilan kepada pemusnah objek semasa yang dibungkus dalam fungsi, maka ada masalah, kerana objek tersebut akan hancur di tengahnya menjalankan kode. Sekiranya panggilan ke fungsi yang mengantrekan peristiwa penghapusan objek semasa, maka tidak ada masalah, kerana objek tersebut akan dimusnahkan setelah selesai pelaksanaannya dan gelung peristiwa akan dimulai.
  3. Isu sebenarnya yang sepertinya disebut dalam anime, "Ini memanggil operasi yang sama berulang kali" - ia akan memanggil DestroyMe() asalkan m_currentHealth <= 0.f dan ada lebih banyak debuff yang tersisa untuk berulang, yang mungkin mengakibatkan DestroyMe() dipanggil berkali-kali, berulang-ulang kali. Gelung harus berhenti selepas yang pertama DestroyMe() panggil, kerana penghapusan objek lebih dari sekali mengakibatkan kerosakan memori, yang kemungkinan akan mengakibatkan kerosakan dalam jangka masa panjang.

Saya tidak begitu pasti mengapa setiap debuf menghilangkan kesihatan, dan bukannya kesihatan yang dikeluarkan hanya sekali, dengan kesan semua debuff berlaku pada kerosakan awal yang diambil, tetapi saya akan menganggap bahawa itu adalah logik permainan yang betul.

Kod yang betul adalah

// the calculation of damage when attacked void DestructibleActor::ReceiveDamage(float sourceDamage) { // apply debuffs auto resolvedDamage = sourceDamage; for (const auto& debuf:m_debufs) { resolvedDamage = debuf.ApplyToDamage(resolvedDamage); m_currentHealth -= resolvedDamage if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); break; } } } 
3
  • Saya harus menunjukkan bahawa kerana saya telah menulis peruntukan memori pada masa lalu, penghapusan memori yang sama tidak semestinya menjadi masalah. Ia juga boleh berlebihan. Semuanya bergantung pada tingkah laku pengagihan. Milik saya hanya bertindak seperti senarai yang dipautkan peringkat rendah sehingga "simpul" untuk data yang dihapus sama ada dibebaskan beberapa kali atau disusun semula beberapa kali (yang hanya sesuai dengan pengalihan penunjuk yang berlebihan). Hasil tangkapan yang baik.
  • Bebas dua kali ganda adalah pepijat, dan secara amnya membawa kepada tingkah laku dan kerosakan yang tidak ditentukan. Walaupun anda mempunyai peruntukan tersuai yang entah bagaimana tidak membenarkan penggunaan semula alamat memori yang sama, bebas dua kali ganda adalah kod yang berbau kerana tidak masuk akal dan anda akan diseru oleh penganalisis kod statik.
  • Sudah tentu! Saya tidak merancangnya untuk tujuan itu. Sebilangan bahasa hanya memerlukan pembahagi kerana kekurangan ciri. Tidak tidak tidak. Saya hanya menyatakan bahawa kemalangan tidak dijamin. Klasifikasi reka bentuk tertentu tidak selalu rosak.