1 điểm bởi GN⁺ 2025-04-24 | 1 bình luận | Chia sẻ qua WhatsApp
  • Lỗi 20 năm tuổi của GTA San Andreas lộ diện trên Windows 11 24H2
    • Đã có báo cáo về lỗi máy bay Skimmer biến mất trong GTA San Andreas trên Windows 11 24H2
    • Vấn đề vẫn không được khắc phục ngay cả khi dùng SilentPatch
    • Trên Windows 11 23H2 không xảy ra lỗi này
    • Tất cả người dùng đã cập nhật lên Windows 11 24H2 đều gặp lỗi này

Điều tra lỗi

Có gì đã xảy ra?

  • Khi cài SilentPatch, game bị treo
  • Phát hiện hiện tượng bị kẹt trong một vòng lặp nhỏ ở CPlane::PreRender
  • Tốc độ cánh quạt của máy bay được đặt cao bất thường
  • Tốc độ cánh quạt được tính theo tỷ lệ với độ cao của máy bay

Tại sao và bằng cách nào?

  • Thiếu tham số cần thiết trong định nghĩa vehicles.ide của Skimmer
  • Trong Vice City, Skimmer được định nghĩa là thuyền
  • Sang San Andreas, nó được đổi thành máy bay nhưng không được thêm các tham số cần thiết

Nguyên nhân gốc rễ thực sự

  • Vấn đề xảy ra do cách sử dụng stack đã thay đổi trong Windows 11 24H2
  • LeaveCriticalSection bắt đầu dùng nhiều không gian stack hơn
  • Trước đây fgetsLeaveCriticalSection không ghi đè lên không gian stack, nhưng giờ thì có

Vì sao đến bây giờ lỗi này mới xuất hiện?

  • Các thay đổi trong Windows 11 24H2 đã làm thay đổi không gian stack
  • Vấn đề phát sinh do game sử dụng biến cục bộ chưa được khởi tạo
  • Trên các nền tảng khác, lỗi này đã được sửa từ trước

Nếu muốn sửa lỗi này trong game?

  • Bản hotfix SilentPatch tiếp theo sẽ bao gồm bản vá mã nguồn
  • Cũng có thể khắc phục bằng cách chỉnh sửa thủ công tệp vehicles.ide

Lời cuối

  • Lỗi này thú vị ở chỗ nó gắn trực tiếp với một bản phát hành OS cụ thể
  • Nó cho thấy thay đổi trong bố cục stack có thể ảnh hưởng đến khả năng tương thích
  • Cần kiểm tra dữ liệu đầu vào và không nên bỏ qua các cảnh báo khi biên dịch

1 bình luận

 
GN⁺ 2025-04-24
Ý kiến Hacker News
  • Nội dung này đúng kiểu có thể mong chờ từ Raymond Chen. Đó là một lời khen ở mức rất cao
  • Thật vui khi thấy nguyên nhân gốc rễ của vấn đề được lần theo sâu hơn
  • Theo quan điểm cá nhân, những gì không thuộc hợp đồng thì nên được xử lý ngẫu nhiên. Ví dụ, nếu một ngôn ngữ không bảo đảm thứ tự lặp của map, thì ngôn ngữ đó nên làm cho nó ngẫu nhiên. Nếu không, mã sẽ trở nên mong manh
  • Không nên bỏ qua các cảnh báo của trình biên dịch. Đoạn mã này rất có thể đã tạo ra cảnh báo trong mã gốc
  • Lỗi trình biên dịch có thể dự đoán ở đây là gì? Có lẽ là không kiểm tra giá trị trả về của scanf để xác nhận nó khớp với số lượng tham số. Nếu không thì trông giống lỗi dữ liệu tệp mà trình biên dịch không thể biết được
  • Tôi luôn thích đọc các bài viết kỹ thuật. Tò mò không biết trong thời đại AI, những bài như thế này sẽ còn hiếm hơn đến mức nào
  • Tôi tự hỏi đã có gì thay đổi trong cách Windows triển khai khóa/mở khóa critical section
  • Cung cấp liên kết cho những người gặp vấn đề truy cập
  • Việc đọc và ghi vượt quá stack lúc nào cũng quá dễ. Chuyện này lẽ ra phải thất bại ngay mới đúng
  • Đã có các biện pháp giảm thiểu như ASLR, trang NX, bảo vệ stack smashing, v.v. Nhưng chúng không thể ngăn hoàn toàn việc đọc dữ liệu cũ nằm ngoài stack
  • Một thử nghiệm về mặt ý tưởng: điều gì sẽ xảy ra nếu phần cứng không cho phép đọc hoặc ghi vào phần chưa được sử dụng của vùng stack
  • Đề xuất một cách theo dõi địa chỉ bắt đầu A của stack, kích thước S và độ sâu hiện tại D
    • Thêm một lệnh để báo cho CPU biết stack tồn tại ở địa chỉ A với kích thước S
    • Thêm một lệnh nhảy để dành trước N byte trên stack
    • Bổ sung khả năng nhận biết stack vào lệnh return hiện có
    • Mọi thao tác đọc hoặc ghi vào vùng stack vượt quá độ sâu hiện tại đều thất bại
    • Trên các kiến trúc mà stack phát triển theo hướng đi xuống, phép toán sẽ được áp dụng theo chiều ngược lại
  • Nhược điểm là nó sẽ cố định một quy ước gọi hàm và bộ quản lý bộ nhớ của CPU sẽ phải giữ rất nhiều trạng thái
  • Stack có mặt ở khắp nơi. Việc để phần cứng nhận biết stack sẽ mở ra các biện pháp giảm thiểu mới
  • Tại sao ý tưởng này không phổ biến? Đã từng có ai thử chưa?
  • Tất cả những phát hiện này chứng minh đây không phải là vấn đề của Windows 11 24H2. Trò chơi đang phụ thuộc vào hành vi không xác định
  • Hành vi không xác định rất xảo quyệt, vì nó khiến bạn tin rằng mình đúng dù thực ra đã phạm sai lầm
  • Nếu một chương trình C hoặc C++ kích hoạt hành vi không xác định, thì bất cứ điều gì cũng có thể xảy ra trong quá trình chạy chương trình
  • Nếu may mắn, chương trình sẽ hiển thị thông báo lỗi phù hợp hoặc bị crash để bạn biết ngay là có vấn đề
  • Nếu kém may mắn, chương trình sẽ âm thầm làm hỏng dữ liệu, và đến khi bạn nhận ra vấn đề thì nguyên nhân đã bị chôn vùi trong lịch sử các lần chạy trước
  • Nếu cực kỳ xui, chương trình sẽ hoạt động đúng như mong muốn cho đến khi bạn thay đổi một đoạn mã không liên quan, hoặc đổi phiên bản trình biên dịch, hệ điều hành, v.v., rồi một lỗi mới xuất hiện
  • Đề xuất các cách tốt hơn với tư cách lập trình viên
    • Đọc, hiểu và ghi nhớ hành vi không xác định trong C hoặc C++, rồi tránh nó
    • Biên dịch ứng dụng ở chế độ debug và so sánh với chế độ release; nếu có khác biệt thì đó là một vấn đề nghiêm trọng
    • Dùng các công cụ như -fsanitize=undefined,address để bắt hành vi không xác định khi chạy
    • Khuyến nghị dùng các ngôn ngữ được quản lý như Java, C#, Python. Hoặc dùng ngôn ngữ mức thấp an toàn như Rust
  • Khuyến khích dùng debugger. Tôi đã nghe nhiều câu chuyện về vấn đề do không dùng debugger
  • Gửi thật nhiều tình cảm tới Silent. Anh ấy đã cải thiện trò chơi tôi yêu thích suốt hơn 10 năm