* [PATCH] flexmember: update comment
@ 2019-05-24 22:01 Paul Eggert
2019-05-24 22:17 ` Bruno Haible
0 siblings, 1 reply; 6+ messages in thread
From: Paul Eggert @ 2019-05-24 22:01 UTC (permalink / raw)
To: bug-gnulib; +Cc: Paul Eggert
* m4/flexmember.m4 (AC_C_FLEXIBLE_ARRAY_MEMBER): Improve comment.
---
ChangeLog | 5 +++++
m4/flexmember.m4 | 10 +++++++---
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 0c4c515a0..efa81e2ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2019-05-24 Paul Eggert <eggert@cs.ucla.edu>
+
+ flexmember: update comment
+ * m4/flexmember.m4 (AC_C_FLEXIBLE_ARRAY_MEMBER): Improve comment.
+
2019-05-20 Bruno Haible <bruno@clisp.org>
setlocale: Improve fallback on macOS.
diff --git a/m4/flexmember.m4 b/m4/flexmember.m4
index 1347068fe..ef6373df2 100644
--- a/m4/flexmember.m4
+++ b/m4/flexmember.m4
@@ -34,10 +34,14 @@ AC_DEFUN([AC_C_FLEXIBLE_ARRAY_MEMBER],
AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [],
[Define to nothing if C supports flexible array members, and to
1 if it does not. That way, with a declaration like 'struct s
- { int n; double d@<:@FLEXIBLE_ARRAY_MEMBER@:>@; };', the struct hack
+ { int n; char d@<:@FLEXIBLE_ARRAY_MEMBER@:>@; };', the struct hack
can be used with pre-C99 compilers.
- When computing the size of such an object, don't use 'sizeof (struct s)'
- as it overestimates the size. Use 'offsetof (struct s, d)' instead.
+ Use 'FLEXSIZEOF (struct s, d, N)' to calculate the size in bytes
+ of such a struct containing an N-element array, as both
+ 'sizeof (struct s) + N * sizeof (char)' and
+ 'offsetof (struct s, d) + N * sizeof (char)'
+ might compute a size that can cause malloc to align storage
+ improperly, even in C11.
Don't use 'offsetof (struct s, d@<:@0@:>@)', as this doesn't work with
MSVC and with C++ compilers.])
else
--
2.21.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] flexmember: update comment
2019-05-24 22:01 [PATCH] flexmember: update comment Paul Eggert
@ 2019-05-24 22:17 ` Bruno Haible
2019-05-24 22:46 ` Paul Eggert
0 siblings, 1 reply; 6+ messages in thread
From: Bruno Haible @ 2019-05-24 22:17 UTC (permalink / raw)
To: bug-gnulib; +Cc: Paul Eggert
Hi Paul,
> + Use 'FLEXSIZEOF (struct s, d, N)' to calculate the size in bytes
> + of such a struct containing an N-element array, as both
> + 'sizeof (struct s) + N * sizeof (char)' and
> + 'offsetof (struct s, d) + N * sizeof (char)'
> + might compute a size that can cause malloc to align storage
> + improperly, even in C11.
I'm confused.
1) What is the alignment problem if the array element type is 'char'?
I would understand an alignment problem if it is 'double'. But with 'char'?
'char' has the size 1, and - except on m68k - also the alignment 1.
2) If
(struct s *) malloc (offsetof (struct s, d) + N * sizeof (char))
should be avoided in favour of
(struct s *) malloc (FLEXSIZEOF (struct s, d, N))
don't we need to apply a 'ceil'-like alignment to the malloc result?
Bruno
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flexmember: update comment
2019-05-24 22:17 ` Bruno Haible
@ 2019-05-24 22:46 ` Paul Eggert
2019-05-24 23:33 ` Bruno Haible
0 siblings, 1 reply; 6+ messages in thread
From: Paul Eggert @ 2019-05-24 22:46 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
On 5/24/19 3:17 PM, Bruno Haible wrote:
> 1) What is the alignment problem if the array element type is 'char'?
Suppose we have a platform where the alignment of each basic type is
equal to its size, where sizeof (int) == 4 and sizeof (char) == 1, and
where we have 'struct s { int n; char d[]; };' and suppose we want to
allocate a 'struct s' with a 3-element flexible array member 'd'. Then
'offsetof (struct s, d) + 3 * sizeof (char)' is 7, and when we call
'malloc (7)' malloc is entitled to assume that memory is being allocated
for an array of 7 one-byte objects, so it can return an address that is
not a multiple of 4, which means that the pointer that malloc returns is
invalid for 'struct s *'. To fix the problem, we can use 'malloc
(FLEXSIZEOF (struct s, d, 3))' instead, as FLEXSIZEOF yields 8 on this
platform, and malloc (8) must return an address that is a multiple of 4.
> don't we need to apply a 'ceil'-like alignment to the malloc result?
No, because if malloc is given an argument like 8 that is a multiple of
sizeof (int), it must return a pointer suitable for 'int *'.
Perhaps I should update the comment to make this all clearer, though it
is hard to be clear and accurate and terse in this area.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flexmember: update comment
2019-05-24 22:46 ` Paul Eggert
@ 2019-05-24 23:33 ` Bruno Haible
2019-05-25 0:34 ` Paul Eggert
0 siblings, 1 reply; 6+ messages in thread
From: Bruno Haible @ 2019-05-24 23:33 UTC (permalink / raw)
To: Paul Eggert; +Cc: bug-gnulib
Hi Paul,
> > 1) What is the alignment problem if the array element type is 'char'?
>
> Suppose we have a platform where the alignment of each basic type is
> equal to its size, where sizeof (int) == 4 and sizeof (char) == 1, and
> where we have 'struct s { int n; char d[]; };' and suppose we want to
> allocate a 'struct s' with a 3-element flexible array member 'd'. Then
> 'offsetof (struct s, d) + 3 * sizeof (char)' is 7, and when we call
> 'malloc (7)' malloc is entitled to assume that memory is being allocated
> for an array of 7 one-byte objects, so it can return an address that is
> not a multiple of 4, which means that the pointer that malloc returns is
> invalid for 'struct s *'. To fix the problem, we can use 'malloc
> (FLEXSIZEOF (struct s, d, 3))' instead, as FLEXSIZEOF yields 8 on this
> platform, and malloc (8) must return an address that is a multiple of 4.
>
> > don't we need to apply a 'ceil'-like alignment to the malloc result?
> No, because if malloc is given an argument like 8 that is a multiple of
> sizeof (int), it must return a pointer suitable for 'int *'.
Oh, I see. Thanks. I was assuming that malloc (N) always returns a
multiple of max_align_t.
> Perhaps I should update the comment to make this all clearer, though it
> is hard to be clear and accurate and terse in this area.
You found the right words now :) - I would expect to see such
explanations in the .h file, not in the .m4 file.
Bruno
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flexmember: update comment
2019-05-24 23:33 ` Bruno Haible
@ 2019-05-25 0:34 ` Paul Eggert
2019-05-25 13:07 ` Bruno Haible
0 siblings, 1 reply; 6+ messages in thread
From: Paul Eggert @ 2019-05-25 0:34 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
[-- Attachment #1: Type: text/plain, Size: 203 bytes --]
On 5/24/19 4:33 PM, Bruno Haible wrote:
> You found the right words now :) - I would expect to see such
> explanations in the .h file, not in the .m4 file.
I gave that a shot by installing the attached.
[-- Attachment #2: 0001-flexmember-update-comments-again.patch --]
[-- Type: text/x-patch, Size: 3772 bytes --]
From eb7977e908bd3b2a1367ab2871647e76055b4ba0 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 24 May 2019 17:31:34 -0700
Subject: [PATCH] flexmember: update comments again
* lib/flexmember.h, m4/flexmember.m4: Improve comments further.
---
ChangeLog | 3 +++
lib/flexmember.h | 25 ++++++++++++++++++++-----
m4/flexmember.m4 | 12 +++---------
3 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index efa81e2ae..2cd6145c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2019-05-24 Paul Eggert <eggert@cs.ucla.edu>
+ flexmember: update comments again
+ * lib/flexmember.h, m4/flexmember.m4: Improve comments further.
+
flexmember: update comment
* m4/flexmember.m4 (AC_C_FLEXIBLE_ARRAY_MEMBER): Improve comment.
diff --git a/lib/flexmember.h b/lib/flexmember.h
index 8e79bce03..431bec11e 100644
--- a/lib/flexmember.h
+++ b/lib/flexmember.h
@@ -33,11 +33,26 @@
# define FLEXALIGNOF(type) _Alignof (type)
#endif
-/* Upper bound on the size of a struct of type TYPE with a flexible
- array member named MEMBER that is followed by N bytes of other data.
- This is not simply sizeof (TYPE) + N, since it may require
- alignment on unusually picky C11 platforms, and
- FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
+/* Yield a properly aligned upper bound on the size of a struct of
+ type TYPE with a flexible array member named MEMBER that is
+ followed by N bytes of other data. The result is suitable as an
+ argument to malloc. For example:
+
+ struct s { int n; char d[FLEXIBLE_ARRAY_MEMBER]; };
+ struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char)));
+
+ FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N),
+ since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is
+ it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size
+ that causes malloc to yield a pointer that is not properly aligned
+ for TYPE; for example, if sizeof (int) == alignof (int) == 4,
+ malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent
+ to malloc (7) and might yield a pointer that is not a multiple of 4
+ (which means the pointer is not properly aligned for struct s),
+ whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is
+ equivalent to malloc (8) and must yield a pointer that is a
+ multiple of 4.
+
Yield a value less than N if and only if arithmetic overflow occurs. */
#define FLEXSIZEOF(type, member, n) \
diff --git a/m4/flexmember.m4 b/m4/flexmember.m4
index ef6373df2..c245ab025 100644
--- a/m4/flexmember.m4
+++ b/m4/flexmember.m4
@@ -34,16 +34,10 @@ AC_DEFUN([AC_C_FLEXIBLE_ARRAY_MEMBER],
AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [],
[Define to nothing if C supports flexible array members, and to
1 if it does not. That way, with a declaration like 'struct s
- { int n; char d@<:@FLEXIBLE_ARRAY_MEMBER@:>@; };', the struct hack
+ { int n; short d@<:@FLEXIBLE_ARRAY_MEMBER@:>@; };', the struct hack
can be used with pre-C99 compilers.
- Use 'FLEXSIZEOF (struct s, d, N)' to calculate the size in bytes
- of such a struct containing an N-element array, as both
- 'sizeof (struct s) + N * sizeof (char)' and
- 'offsetof (struct s, d) + N * sizeof (char)'
- might compute a size that can cause malloc to align storage
- improperly, even in C11.
- Don't use 'offsetof (struct s, d@<:@0@:>@)', as this doesn't work with
- MSVC and with C++ compilers.])
+ Use 'FLEXSIZEOF (struct s, d, N * sizeof (short))' to calculate
+ the size in bytes of such a struct containing an N-element array.])
else
AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [1])
fi
--
2.21.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] flexmember: update comment
2019-05-25 0:34 ` Paul Eggert
@ 2019-05-25 13:07 ` Bruno Haible
0 siblings, 0 replies; 6+ messages in thread
From: Bruno Haible @ 2019-05-25 13:07 UTC (permalink / raw)
To: Paul Eggert; +Cc: bug-gnulib
Hi Paul,
> I gave that a shot by installing the attached.
Thanks.
I found the relevant references now, in [1]. The fact that some people see it not
as a property of the malloc() function but as a GCC bug [2] indicates that it should
also apply when alloca() is used to allocate the memory. (In this case, a program
would not crash when it makes out-of-bounds accesses on the stack, but valgrind
may still report accesses to uninitialized memory.)
Bruno
[1] https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=4c32543a4f05706ca3a8c8d583a5fb35d0e58828
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66661
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2019-05-25 13:07 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-24 22:01 [PATCH] flexmember: update comment Paul Eggert
2019-05-24 22:17 ` Bruno Haible
2019-05-24 22:46 ` Paul Eggert
2019-05-24 23:33 ` Bruno Haible
2019-05-25 0:34 ` Paul Eggert
2019-05-25 13:07 ` Bruno Haible
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).