Anonim

AIMBOT 2.0

Sa episode 1 ng New Game 2, bandang 9:40, may kuha ng code na isinulat ni Nene:

Narito ito sa form ng teksto kasama ang mga komentong isinalin:

// 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(); } } } 

Matapos ang pagbaril, sinabi ni Umiko, na nakaturo sa for loop, na ang dahilan kung bakit bumagsak ang code ay mayroong isang walang katapusan na loop.

Hindi ko talaga alam ang C ++ kaya hindi ako sigurado kung totoo ang sinasabi niya.

Mula sa nakikita ko, ang para sa loop ay umuulit lamang sa pamamagitan ng mga debuf na kasalukuyang mayroon ang Actor. Maliban kung ang Actor ay may isang walang katapusang halaga ng mga debufs, sa palagay ko hindi ito maaaring maging isang walang katapusang loop.

Ngunit hindi ako sigurado sapagkat ang tanging dahilan lamang na may isang pagbaril ng code ay nais nilang maglagay ng isang itlog ng easter dito, tama ba? Makukuha lang namin ang isang shot ng likod ng laptop at marinig si Umiko na nagsasabing "Oh mayroon kang isang infinite loop doon". Ang katotohanan na talagang ipinakita nila ang ilang code ay naiisip ko na kahit papaano ang code ay isang easter egg ng ilang uri.

Ang code ba ay talagang lilikha ng isang walang katapusan na loop?

8
  • Marahil ay kapaki-pakinabang: karagdagang screenshot ng Umiko na nagsasabing "Ito ay pagtawag sa parehong operasyon paulit-ulit ", na maaaring hindi maipakita sa code.
  • Oh! Hindi ko alam yun! @AkiTanaka ang sub na napanood ko ay nagsasabing "infinite loop"
  • @LoganM Hindi talaga ako sang-ayon. Hindi lamang ang OP ay may isang katanungan tungkol sa ilang mga source code na nangyari na nagmula sa isang anime; Ang tanong ni OP ay tungkol sa isang partikular na pahayag na ginawa tungkol sa ang source code ng isang character sa anime, at mayroong isang sagot na nauugnay sa anime, lalo ang "Crunchyroll tapos na goofed at mali ang pagkakasalin sa linya".
  • @senshin Sa palagay ko binabasa mo kung ano ang gusto mong tanong, kaysa sa kung ano talaga ang tinanong. Ang tanong ay nagbibigay ng ilang source code at tinanong kung bumubuo ito ng isang walang katapusang loop bilang real-life C ++ code. Bagong laro! ay isang gawaing kathang-isip; hindi na kailangan ang code na ipinakita dito upang sumunod sa mga pamantayan sa totoong buhay. Ang sinabi ni Umiko tungkol sa code ay mas may kapangyarihan kaysa sa anumang mga pamantayan ng C ++ o tagatala. Ang nangungunang (tinanggap) na sagot ay walang pagbanggit ng anumang impormasyon sa-uniberso. Sa palagay ko ay maaaring tanungin ang isang paksang pinag-uusapan tungkol dito sa isang mahusay na sagot, ngunit tulad ng pagbigkas ng salita hindi ito.

Ang code ay hindi isang walang hanggan loop ngunit ito ay isang bug.

Mayroong dalawang (posibleng tatlo) na mga isyu:

  • Kung walang mga debufs na naroroon ay walang mailalapat na pinsala
  • Ang labis na pinsala ay mailalapat kung mayroong higit sa 1 debuf
  • Kung ang DestroyMe () ay agad na tinatanggal ang object at mayroon pa ring m_debufs upang maproseso ang loop ay papatayin sa isang tinanggal na bagay at basurahan ang memorya. Karamihan sa mga engine ng laro ay may isang nawasak na pila upang gumana ito at higit pa upang maaaring hindi ito isang isyu.

Ang aplikasyon ng pinsala ay dapat na nasa labas ng loop.

Narito ang naitama na pagpapaandar:

// 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 Nasa Code Review ba tayo? : D
  • Ang 4 na float ay mahusay para sa kalusugan kung hindi ka lumampas sa 16777216 HP. Maaari mo ring itakda ang kalusugan sa walang hanggan upang lumikha ng isang kaaway maaari kang pindutin ngunit hindi mamamatay, at magkaroon ng isang isang pumatay na pag-atake gamit ang walang katapusang pinsala na hindi pa rin pumatay ng isang walang katapusang character ng HP (ang resulta ng INF-INF ay NaN) ngunit papatayin lahat. Napaka kapaki-pakinabang.
  • 1 @cat Sa pamamagitan ng kombensiyon sa maraming mga pamantayan sa pag-coding ang m_ Ang ibig sabihin ng unlapi ay isang variable ng miyembro. Sa kasong ito ang isang variable ng miyembro ng DestructibleActor.
  • 2 @HotelCalifornia Sumasang-ayon ako na mayroong isang maliit na pagkakataon ApplyToDamage ay hindi gumagana tulad ng inaasahan ngunit sa halimbawang kaso na ibibigay mo sasabihin ko ApplyToDamage din kailangang muling gawing muli upang mangailangan ng pagpasa nito sa orihinal sourceDamage pati na rin upang makalkula nito ang debuf nang maayos sa mga kasong iyon. Upang maging isang ganap na pedant: sa puntong ito ang impormasyon ng dmg ay dapat na isang istruktura na kasama ang orihinal na dmg, kasalukuyang dmg, at ang likas na (mga) pinsala pati na rin kung ang mga debuf ay may mga bagay tulad ng "kahinaan sa sunog". Mula sa karanasan hindi ito matagal bago ang anumang disenyo ng laro na may mga debuf na hinihiling ang mga ito.
  • 1 @StephaneHockenhull mahusay na sinabi!

Ang code ay tila hindi lumikha ng isang walang katapusan na loop.

Ang tanging paraan na ang loop ay magiging walang hanggan ay kung

debuf.ApplyToDamage(resolvedDamage); 

o

DestroyMe(); 

ay upang magdagdag ng mga bagong item sa m_debufs lalagyan

Ito ay tila hindi malamang. At kung ito ang kaso, ang programa ay maaaring mag-crash dahil sa pagbabago ng lalagyan habang paulit-ulit.

Malamang na mag-crash ang programa dahil sa tawag sa DestroyMe(); na maaaring masisira ang kasalukuyang bagay na kasalukuyang nagpapatakbo ng loop.

Maaari nating isipin ito bilang isang cartoon kung saan ang 'masamang tao' ay nakakita ng isang sangay upang mahulog dito ang 'mabuting tao', ngunit napagtanto na huli na siya ay nasa maling panig ng hiwa. O ang Midgaard Snake na kumakain ng sariling buntot.


Dapat ko ring idagdag na ang pinakakaraniwang sintomas ng isang walang katapusan na loop ay na-freeze nito ang programa o ginagawa itong hindi tumutugon. Masisira nito ang programa kung ito ay naglalaan ng memorya ng paulit-ulit, o gumagawa ng isang bagay na nagtatapos sa paghahati ng zero, o mga kagustuhan.


Batay sa komento ni Aki Tanaka,

Marahil ay kapaki-pakinabang: karagdagang screenshot ng Umiko na sinasabi na "Ito ay tumatawag nang paulit-ulit sa parehong operasyon", na maaaring hindi maipakita sa code.

"Paulit-ulit itong tumatawag sa parehong operasyon" Ito ay mas malamang.

Ipagpalagay na DestroyMe(); ay hindi idinisenyo upang tawaging higit sa isang beses, mas malamang na magdulot ng isang pag-crash.

Ang isang paraan upang ayusin ang isyung ito ay upang baguhin ang if para sa isang bagay tulad nito:

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

Lalabas ito sa loop kapag nawasak ang DestructibleActor, tinitiyak na 1) ang DestroyMe ang pamamaraan ay tinatawag na isang beses lamang at 2) huwag maglagay ng mga buff nang walang kwenta sa sandaling ang bagay ay itinuring na patay na.

2
  • 1 Ang paglabas ng para sa loop kapag ang kalusugan <= 0 ay tiyak na isang mas mahusay na ayusin kaysa maghintay hanggang matapos ang loop upang suriin ang kalusugan.
  • Sa palagay ko gusto ko break sa labas ng loop, at tapos tawagan DestroyMe(), para lang maging ligtas

Mayroong maraming mga isyu sa code:

  1. Kung walang mga debufs, walang pinsala na magagawa.
  2. DestroyMe() delikado ang tunog ng pangalan ng pag-andar. Nakasalalay sa kung paano ito ipinatupad, maaaring ito ay maaaring maging isang isyu. Kung ito ay isang tawag lamang sa destructor ng kasalukuyang object na nakabalot sa isang pagpapaandar, pagkatapos ay mayroong isang isyu, dahil ang object ay nawasak sa gitna nito na nagpapatupad ng code. Kung ito ay isang tawag sa isang pagpapaandar na pumipila sa kaganapan ng pagtanggal ng kasalukuyang bagay, kung gayon walang isyu, dahil ang bagay ay nawasak matapos nitong makumpleto ang pagpapatupad nito at ang loop ng kaganapan ay sumisipa.
  3. Ang aktwal na isyu na tila nabanggit sa anime, ang "It was calling the same operation over and over again" - tatawag ito DestroyMe() hangga't m_currentHealth <= 0.f at maraming natitirang mga debuff upang umulit, na maaaring magresulta DestroyMe() tinatawag na maraming beses, paulit-ulit. Ang loop ay dapat huminto pagkatapos ng una DestroyMe() tumawag, dahil ang pagtanggal ng isang bagay na higit sa isang beses ay nagreresulta sa katiwalian sa memorya, na maaaring magresulta sa isang pag-crash sa pangmatagalan.

Hindi ko talaga sigurado kung bakit ang bawat debuf ay aalisin ang kalusugan, sa halip na ang kalusugan ay naalis lamang ng isang beses, na may mga epekto ng lahat ng mga debuff na inilapat sa paunang pinsala na kinuha, ngunit ipalagay ko na ang tamang lohika ng laro.

Ang tamang code ay magiging

// 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
  • Dapat kong ipahiwatig na tulad ng pagsulat ko ng mga tagapag-alok ng memorya sa nakaraan, ang pagtanggal ng parehong memorya ay hindi dapat maging isang isyu. Maaari din itong maging kalabisan. Ang lahat ay nakasalalay sa pag-uugali ng tagapaglaan. Ang akin ay kumilos lamang tulad ng isang mababang antas ng naka-link na listahan kaya ang "node" para sa tinanggal na data ay maaaring maitakda nang libre nang maraming beses o muling na-redelet ng maraming beses (na tumutugma lamang sa mga labis na pag-redirect ng pointer). Magandang catch man.
  • Ang double-free ay isang bug, at sa pangkalahatan ay humahantong sa hindi natukoy na pag-uugali at pag-crash. Kahit na mayroon kang isang pasadyang tagapaglaan na kahit papaano ay hindi pinapayagan ang muling paggamit ng parehong address ng memorya, ang dobleng-libre ay isang mabahong code dahil wala itong kahulugan at masisigawan ka ng mga static na tagapag-analisa ng code.
  • Syempre! Hindi ko ito dinisenyo para sa hangaring iyon. Ang ilang mga wika ay nangangailangan lamang ng isang tagapaglaan dahil sa mga kakulangan ng mga tampok. Hindi hindi Hindi. Sinasabi ko lamang na ang isang pag-crash ay hindi garantisado. Ang ilang mga pag-uuri ng disenyo ay hindi laging nag-crash.