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

refactor: replace (sizeof(a)/sizeof(a[0])) with C++17 std::size #20429

Merged

Conversation

theStack
Copy link
Contributor

@theStack theStack commented Nov 20, 2020

This refactoring PR picks up the idea of #19626 and replaces all occurences of sizeof(x)/sizeof(x[0]) (or sizeof(x)/sizeof(*x), respectively) with the now-available C++17 std::size (as suggested by sipa), making the macro ARRAYLEN obsolete.

As preparation for this, two other changes are done to eliminate sizeof(x)/sizeof(x[0]) usage:

  • all places where arrays are iterated via an index are changed to use C++11 range-based for loops If the index' only purpose is to access the array element (as suggested by MarcoFalke).
  • std::vector initializations are done via std::begin and std::end rather than using pointer arithmetic to calculate the end (also suggested by MarcoFalke).

@theStack theStack changed the title refactor: replace (sizeof(a)/sizeof(a[0]) with C++17 std::size refactor: replace (sizeof(a)/sizeof(a[0])) with C++17 std::size Nov 20, 2020
@fanquake
Copy link
Member

Concept ACK

@laanwj
Copy link
Member

laanwj commented Nov 20, 2020

Although I agree this is slightly better, I'm honestly not sure we should be doing refactors all over the place just for the sake of using C++17. It's always possible to introduce a subtle issue. We did have a "new code and code that is changed anyway" policy at the time of C++11 at least.

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 20, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@practicalswift
Copy link
Contributor

practicalswift commented Nov 20, 2020

Concept ACK

While I agree that we shouldn't introduce C++17 just for the sake of it I think this one is a clear win since it removes a potentially unsafe idiom with a safer replacement. (To be clear: I think our current usages of this idiom are safe, but I think removing an unsafe idiom from the code base reduces the risk of accidental introduction of bugs due to said unsafe idiom in the future due to copy pasta, imitation, etc.)

sizeof(arr) / sizeof(arr[0]) is a potentially unsafe idiom due to this gotcha:

$ cat sizeof_gotcha.cpp
#include <iostream>

int f1(int arr[]) { return sizeof(arr) / sizeof(arr[0]); }

// Will give a compile time error:
// int f2(int arr[]) { return std::size(arr); }

int main() {
  int arr[]{1, 2, 3};
  std::cout << "sizeof(arr) / sizeof(arr[0]) = " << sizeof(arr) / sizeof(arr[0]) << "\n";
  std::cout << "sizeof(arr) / sizeof(arr[0]) in f1 = " << f1(arr) << "\n";
  std::cout << "std::size(arr) = " << std::size(arr) << "\n";
  // std::cout << "std::size(arr) in f2 = " << f2(arr) << "\n";
}
$ ./sizeof_gotcha
sizeof(arr) / sizeof(arr[0]) = 3
sizeof(arr) / sizeof(arr[0]) in f1 = 2
std::size(arr) = 3

Note the "unexpected" result from sizeof-based f1 due to pointer decay.

Note also how the std::size-based f2 errors out at compile time instead.

I've verified that this change is complete by comparing the suggested changes against:

$ git grep -E '(sizeof\(.*/.*sizeof\(|ARRAYLEN)' ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" \
      ":(exclude)src/univalue/" ":(exclude)src/crypto/"

@laanwj
Copy link
Member

laanwj commented Nov 22, 2020

sizeof(arr) / sizeof(arr[0]) is a potentially unsafe idiom due to this gotcha:

Yes, agree in this specific case.

Light code review ACK.

@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft".

@fanquake
Copy link
Member

ACK after rebase

@theStack theStack force-pushed the 20201119-refactor-replace-sizeof-by-std_size branch from f0baead to 7841a09 Compare January 31, 2021 11:15
@theStack
Copy link
Contributor Author

Rebased on master.

src/bench/data.cpp Outdated Show resolved Hide resolved
src/qt/networkstyle.cpp Outdated Show resolved Hide resolved
Removes the macro ARRAYLEN and also substitutes all other uses of the same
"sizeof(a)/sizeof(a[0])" pattern by std::size, available since C++17.
@theStack theStack force-pushed the 20201119-refactor-replace-sizeof-by-std_size branch from 7841a09 to e829c9a Compare January 31, 2021 16:39
@theStack
Copy link
Contributor Author

Force-pushed with suggestions of MarcoFalke, see #20429 (comment) and #20429 (comment)). Also updated the PR description.
Note due to reordering of the commits, its timestamps are also out-of-order now, let me know if this is a problem.

@practicalswift
Copy link
Contributor

cr ACK e829c9a: patch looks correct

Copy link
Member

@fanquake fanquake left a comment

Choose a reason for hiding this comment

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

ACK e829c9a

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

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

review ACK e829c9a 🌩

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

review ACK e829c9afbf75e930db6c3fe77a269b0af5e7a3ad 🌩
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUjxnAv+IIfvDbq/F7CYc56GGB/cpjXOouSirKbLpzFCtLN5qf3Nm8YaC2D4falz
FjP6yiVo2wclJYOwKA2hJAwAADynBBOxWKyol2iT7ps6QFthPc+AyXMph3JO49t4
XBh0Jx6oRz/LyT4A/gWsHsMoufDhIh+P9xJ0gyG+0EIuiOIYed3y5JOQdaCecRUg
Fz0wdTjxIoyGI4NiHOc3a8wQWyuLWjzb6X9LGGXjw2vA+muP8343CPjzbUqcrbSf
UJWszfJZCdzTvgJzM3PHWEv8xqeJXuMwLNiUTiBzliBaDbkFw8BkV1hO5Xufbxye
JdQjS08db1gfOBnQT4jm+Np5c3K6OGsmlH7L1nOChaDBJh2Zi8HirUMOrgDZ6vii
2K/ThPNnvoLLhcNqRk51/F2jvjkkWwWNzfXux6H2t7K4EBckznGmTAD+BRO8ZvMi
IbvOwlzKr+ytFV6+Dzt9bZdnOtl+P56pswjd2G1LfWOa+qExOiCKFZZA1hbiCdH4
LbTt/Lm2
=sj81
-----END PGP SIGNATURE-----

Timestamp of file with hash 299d77a070c17af50cb1cc6964e89dfae768fc6598b33fd733eacddbbf5c15be -

@maflcko maflcko merged commit cd66d8b into bitcoin:master Feb 18, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 18, 2021
deadalnix pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Mar 10, 2022
Summary:
> refactor: iterate arrays via C++11 range-based for loops if idx is not needed

> refactor: init vectors via std::{begin,end} to avoid pointer arithmetic

> refactor: replace sizeof(a)/sizeof(a[0]) by std::size (C++17)
>
> Removes the macro ARRAYLEN and also substitutes all other uses of the same
> "sizeof(a)/sizeof(a[0])" pattern by std::size, available since C++17.

This is a backport of [[bitcoin/bitcoin#20429 | core#20429]] and one commit from [[bitcoin/bitcoin#20245 | core#20245]]
bitcoin/bitcoin@fa3967e

The commit from core#20245 is doing the same thing as core#20249, and is unrelated to the rest of its PR, so the partial backport will not cause any issue.

Test Plan: `ninja all check-all bitcoin-bench`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D11140
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants