AIMBOT 2.0
New Game 2의 에피소드 1, 9시 40 분경 Nene이 작성한 코드가 있습니다.
다음은 주석이 번역 된 텍스트 형식입니다.
// 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(); } } }
촬영 후 Umiko는 for 루프를 가리키며 코드가 충돌 한 이유는 무한 루프가 있기 때문이라고 말했습니다.
저는 C ++를 잘 모릅니다. 그래서 그녀가 말하는 것이 사실인지 잘 모르겠습니다.
내가 볼 수 있듯이 for 루프는 액터가 현재 가지고있는 디버프를 반복하고 있습니다. 액터가 무한한 양의 디버프를 가지지 않는 한, 나는 그것이 무한 루프가 될 수 있다고 생각하지 않습니다.
하지만 코드가 찍힌 유일한 이유는 이스터 에그를 여기에 넣고 싶었 기 때문입니다. 우리는 방금 노트북 뒷면을 촬영하고 Umiko가 "오, 거기에 무한 루프가 있습니다"라고 말하는 것을 들었을 것입니다. 그들이 실제로 어떤 코드를 보여 주었다는 사실은이 코드가 일종의 이스터 에그라고 생각하게합니다.
코드가 실제로 무한 루프를 생성합니까?
8- 아마도 도움이 될 것입니다. Umiko가 "그것은 같은 작업을 호출 코드에 표시되지 않을 수 있습니다.
- 오! 나는 그것을 몰랐다! @AkiTanaka 내가 본 서브는 "무한 루프"라고 말한다
- @LoganM 정말 동의하지 않습니다. OP가 애니메이션에서 나온 소스 코드에 대한 질문 만있는 것은 아닙니다. OP의 질문은 특정 진술에 관한 것입니다. 약 애니메이션에 등장하는 캐릭터에 의한 소스 코드와 애니메이션 관련 답변이 있습니다. 즉, "Crunchyroll이 구핑을하여 줄을 잘못 번역했습니다."
- @senshin 실제 질문이 아닌 질문에 대한 내용을 읽고있는 것 같습니다. 이 질문은 몇 가지 소스 코드를 제공하고 실제 C ++ 코드로 무한 루프를 생성하는지 여부를 묻습니다. 새로운 게임! 허구의 작품입니다. 실제 표준을 따르기 위해 여기에 제공된 코드가 필요하지 않습니다. Umiko가 코드에 대해 말하는 것은 어떤 C ++ 표준이나 컴파일러보다 더 권위가 있습니다. 최상위 (허용) 답변에는 우주 내 정보에 대한 언급이 없습니다. 주제에 관한 질문이 좋은 답변으로 질문 될 수 있다고 생각하지만,이 말은 그렇지 않습니다.
코드는 무한 루프는 아니지만 버그입니다.
두 가지 (아마도 세 가지) 문제가 있습니다.
- 디버프가 없으면 손상이 전혀 적용되지 않습니다.
- Debuf가 1 개 이상일 경우 과도한 손상이 적용됩니다.
- DestroyMe ()가 즉시 객체를 삭제하고 처리 할 m_debufs가 아직 남아있는 경우 루프는 삭제 된 객체 및 메모리를 폐기하는 동안 실행됩니다. 대부분의 게임 엔진에는이 문제를 해결하기위한 파괴 대기열이 있으므로 문제가되지 않을 수 있습니다.
손상의 적용은 루프 외부에 있어야합니다.
수정 된 기능은 다음과 같습니다.
// 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 우리는 코드 검토 중입니까? :디
- 16777216 HP를 넘지 않으면 4 개의 수레가 건강에 좋습니다. 체력을 무한으로 설정하여 적중 할 수 있지만 죽지는 않을 적을 만들고, 무한 HP 캐릭터를 죽이지 않는 무한 피해를 사용하여 원킬 공격을 할 수도 있습니다 (INF-INF의 결과는 NaN입니다). 다른 모든 것을 죽일 것입니다. 그래서 매우 유용합니다.
- 1 @cat 많은 코딩 표준에서 관례 적으로
m_
접두사는 멤버 변수임을 의미합니다. 이 경우 멤버 변수DestructibleActor
. - 2 @HotelCalifornia 작은 기회가 있다는 데 동의합니다
ApplyToDamage
예상대로 작동하지 않지만 예제의 경우ApplyToDamage
또한 원본을 전달하도록 재 작업해야합니다.sourceDamage
또한 이러한 경우 debuf를 올바르게 계산할 수 있습니다. 절대 pedant가 되려면 :이 시점에서 dmg 정보는 원래 dmg, 현재 dmg 및 손상의 특성을 포함하는 구조체 여야합니다. 경험상 얼마 지나지 않아 디버프가있는 게임 디자인이이를 요구합니다. - 1 @StephaneHockenhull 잘 말했습니다!
코드가 무한 루프를 생성하지 않는 것 같습니다.
루프가 무한 할 수있는 유일한 방법은
debuf.ApplyToDamage(resolvedDamage);
또는
DestroyMe();
새로운 항목을 m_debufs
컨테이너.
이것은 가능성이없는 것 같습니다. 이 경우 반복되는 동안 컨테이너를 변경하면 프로그램이 충돌 할 수 있습니다.
프로그램은 다음 호출로 인해 충돌 할 가능성이 높습니다. DestroyMe();
현재 루프를 실행중인 현재 개체를 파괴하는 것으로 추정됩니다.
'나쁜 놈'이 나뭇 가지를보고 '좋은 놈'이 떨어지게하는 만화라고 생각할 수 있지만, 그가 잘못된 편에 있다는 것을 너무 늦게 깨닫는 것입니다. 또는 자신의 꼬리를 먹는 미드 가드 뱀.
또한 무한 루프의 가장 일반적인 증상은 프로그램이 멈추거나 응답하지 않는 것입니다. 반복적으로 메모리를 할당하거나 0으로 나누는 작업을 수행하면 프로그램이 중단됩니다.
Aki Tanaka의 코멘트를 바탕으로,
아마도 도움이 될 것입니다. Umiko가 "동일한 작업을 반복해서 호출했습니다"라는 추가 스크린 샷. 코드에 표시되지 않을 수 있습니다.
"그것은 같은 작업을 계속해서 부르고 있었다" 더 가능성이 있습니다.
그것을 가정 DestroyMe();
두 번 이상 호출되도록 설계되지 않은 경우 충돌을 일으킬 가능성이 더 큽니다.
이 문제를 해결하는 방법은 if
다음과 같이 :
if (m_currentHealth <= 0.f) { m_currentHealth = 0.f; DestroyMe(); break; }
이것은 DestructibleActor가 파괴 될 때 루프를 종료합니다. DestroyMe
메서드는 한 번만 호출되며 2) 이미 죽은 것으로 간주되는 개체가 있으면 쓸데없이 버프를 적용하지 마십시오.
- 1 상태 <= 0 일 때 for 루프를 벗어나는 것은 루프가 끝날 때까지 대기하여 상태를 확인하는 것보다 확실히 더 나은 해결 방법입니다.
- 나는 아마
break
루프에서 벗어나 그때 요구DestroyMe()
, 안전을 위해
코드에는 몇 가지 문제가 있습니다.
- 디버프가 없으면 손상이 발생하지 않습니다.
DestroyMe()
함수 이름이 위험 해 보입니다. 구현 방법에 따라 문제가 될 수도 있고 아닐 수도 있습니다. 함수에 래핑 된 현재 개체의 소멸자에 대한 호출 인 경우 코드를 실행하는 동안 개체가 파괴되므로 문제가 있습니다. 현재 객체의 삭제 이벤트를 큐에 넣는 함수에 대한 호출이라면 객체가 실행을 완료하고 이벤트 루프가 시작된 후 삭제되므로 문제가 없습니다.- 애니메이션에서 언급 된 것처럼 보이는 실제 문제 "같은 작업을 반복해서 호출했습니다"-
DestroyMe()
하는 한m_currentHealth <= 0.f
반복해야 할 디버프가 더 많이 남아 있습니다.DestroyMe()
여러 번, 계속해서 호출됩니다. 루프는 첫 번째 이후에 중지되어야합니다.DestroyMe()
객체를 두 번 이상 삭제하면 메모리가 손상되어 장기적으로 충돌이 발생할 가능성이 있기 때문입니다.
나는 왜 모든 디버프가 체력을 한 번만 빼앗기고, 모든 디버프의 효과가 초기 피해에 적용되는 대신 왜 체력을 빼앗는 지 잘 모르겠지만 이것이 올바른 게임 논리라고 가정 할 것입니다.
올바른 코드는
// 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 - 과거에 메모리 할당자를 작성 했으므로 동일한 메모리를 삭제하는 것이 문제가 될 필요는 없다는 점을 지적해야합니다. 중복 될 수도 있습니다. 그것은 모두 할당 자의 행동에 달려 있습니다. 내 것은 저수준 연결 목록처럼 작동했기 때문에 삭제 된 데이터에 대한 "노드"가 여러 번 해제되거나 여러 번 다시 삭제됩니다 (중복 포인터 리디렉션에 해당함). 그래도 좋은 캐치.
- Double-free는 버그이며 일반적으로 정의되지 않은 동작과 충돌로 이어집니다. 동일한 메모리 주소의 재사용을 허용하지 않는 사용자 지정 할당자가 있더라도 double-free는 의미가 없으며 정적 코드 분석기에 의해 소리를 지르기 때문에 냄새 나는 코드입니다.
- 물론이야! 나는 그 목적을 위해 그것을 디자인하지 않았습니다. 일부 언어는 기능이 없기 때문에 할당자가 필요합니다. 아니, 아니. 나는 단지 충돌이 보장되지 않는다고 말하고 있었다. 특정 디자인 분류가 항상 충돌하는 것은 아닙니다.