Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize: Move some arrays to std::array #412

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

GravisZro
Copy link
Contributor

@GravisZro GravisZro commented Jun 1, 2024

Pull Request Type

  • Runtime changes
    • Other changes

Description

The ultimate goal is to switch several variables to vectors in order to expand game limitations but the first step is to switch C arrays to std::array so that we ensure that memory bounds are respected. There is more in-depth work to adapting how the arrays are used but I didn't want to make the PR too large.

Other stuff

  • The SAVE_DATA_TABLE was replaced with a template function version
  • The OBJNUM macro was used in place of obj - Objects
  • Three bugs found and fixed.
    • In ObjInitGeneric in for loop where obj_info wasn't being used.
    • Twice in WeaponFire.cpp where fq.thisobjnum was being assigned Objects - obj instead of obj - Objects (replaced with OBJNUM macro)

Checklist

  • I have tested my changes locally and verified that they work as intended.
  • I have documented any new or modified functionality.
  • I have reviewed the changes to ensure they do not introduce any unnecessary complexity or duplicate code.
  • I understand that by submitting this pull request, I am agreeing to license my contributions under the project's license.

Also replaces a macro with a template function
@GravisZro GravisZro force-pushed the modernize/array branch 7 times, most recently from cd12329 to 86ec6c3 Compare June 1, 2024 23:06
@winterheart
Copy link
Collaborator

I don't see value of these changes. If you trying to solve particular issue, focus on particular part of code. General rule of thumb: "Don't fix that aren't broken".

Bugfixes
- In `ObjInitGeneric` in for loop where `obj_info` wasn't being used.
- Twice in WeaponFire.cpp where `fq.thisobjnum` was being assigned `Objects - obj` instead of `obj - Objects`
@GravisZro
Copy link
Contributor Author

I don't see value of these changes.

That's your mistake because there are currently significant issues open that are likely due to memory access issues.

@GravisZro GravisZro marked this pull request as ready for review June 2, 2024 01:06
@winterheart
Copy link
Collaborator

I don't see value of these changes.

That's your mistake because there are currently significant issues open that are likely due to memory access issues.

Prove it, please. Do you have checked code with Valgrind, is there memory issues on changed code? Do all changed in this PR code suffer these issues?

@GravisZro
Copy link
Contributor Author

The purpose of the changes are to ensure that if a memory violation occurs that it will immediately be caught rather than continue, possibly crashing at a later point. I don't understand why you are being so oppositional to improving the code's reliability. Also, I did point out that I found and fixed some bugs while doing this.

@GravisZro
Copy link
Contributor Author

@winterheart
Do you not want bugfixes? This contains bugfixes.

@@ -1625,7 +1625,7 @@ const char *const Ai_movement_subtype_walking_strings[MAX_AI_INIT_MOVEMENT_SUBTY
#define AI_MAX_MELEE_RANGE 5.0f

int AI_NumRendered;
int AI_RenderedList[MAX_OBJECTS];
std::array<int, MAX_OBJECTS> AI_RenderedList;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as we're doing these conversions, let's default-initialize the elements in the arrays:

Suggested change
std::array<int, MAX_OBJECTS> AI_RenderedList;
std::array<int, MAX_OBJECTS> AI_RenderedList{};

Both T[N] and std::array<T, N> default-initialize only the array object, not the array elements. IE, this gives an indeterminate value:

std::array<int, 4> arr;
int val = arr[0];
// val is indeterminate

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean... OK but I was expecting most of these to eventually be changed to std::vector.

Copy link
Contributor

@tophyr tophyr Jun 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vectors would be preferable, definitely. I'm fine with not adding the explicit initialization in this changeset.

Copy link
Contributor

@tophyr tophyr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noticed what i think is a problem in scripts/LEVEL15.cpp - added array initialization objects. maybe some find-replace artifacts?

don't love the added [[gnu::packed]] attribute in Descent3/aistruct.h either.

beyond the above, added some suggestions but this looks largely fine to me.

Descent3/WeaponFire.cpp Show resolved Hide resolved
@@ -713,17 +715,17 @@ struct ain_weapon_hit_info {

#define AI_MEM_DEPTH 5

struct ai_mem {
struct [[gnu::packed]] ai_mem {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is struct packing needed? without context, this seems smelly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also [[gnu::packed]] isn't portable, MSVC will just ignore the unknown attribute with warning C5030: attribute [[gnu::packed]] is not recognized.
I believe #pragma pack is supported by all recent compiler versions nowadays.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tophyr this was part of something else I was working on.
@pzychotic MSVC is perpetually behind both GCC and clang. You would be better off using clang/llvm on windows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't about what I use, it's about what this project does. I linked to the current CI build log, because we do use MSVC here and that attribute is being ignored in our windows builds. Unless this projects decides to be GCC/Clang only, this issue remains.
Also don't try to tell me which build environment I have to use, just because you don't like it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really a problem because it's being removed.

Descent3/aistruct.h Show resolved Hide resolved
Descent3/fireball.cpp Show resolved Hide resolved
Descent3/gamesave.cpp Show resolved Hide resolved
Descent3/multi.h Show resolved Hide resolved
scripts/LEVEL15.cpp Show resolved Hide resolved
scripts/LEVEL15.cpp Show resolved Hide resolved
scripts/LEVEL15.cpp Show resolved Hide resolved
@tophyr
Copy link
Contributor

tophyr commented Jun 7, 2024

The purpose of the changes are to ensure that if a memory violation occurs that it will immediately be caught rather than continue

@GravisZro for what it's worth, I didn't notice any changes here (other than the use of std::array::fill() over memset()) that actually add bounds-checking. std::array doesn't perform bounds checking via its iterators or operator[]. I do think that we should move to std::array; I just want to call out that the type itself adds no inherent safety. The additional safety will come when we transition to iterator for loops (for (auto const& foo : foos) etc) and stdlib algorithms.

@GravisZro
Copy link
Contributor Author

GravisZro commented Jun 9, 2024

std::array doesn't perform bounds checking via its iterators or operator[]

The C++ standard doesn't not specify the behavior of accessing nonexistent elements using operator[]. However, common implementations like GCC's libstdc++ will do bounds checking.

Copy link
Contributor

@tophyr tophyr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all great, modulo the [[gnu::packed]] annotation.

scripts/LEVEL15.cpp Show resolved Hide resolved
@jengelh
Copy link
Contributor

jengelh commented Aug 30, 2024

std::array doesn't perform bounds checking via its iterators or operator[]

The C++ standard doesn't not specify the behavior of accessing nonexistent elements using operator[]. However, common implementations like GCC's libstdc++ will do bounds checking.

But also only in specific debug builds (-D_GLIBCXX_DEBUG=1). For guaranteed bounds checking, there has always been at().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants