> On Dec 7, 2024, at 03:57, Martin Uecker <uec...@tugraz.at> wrote: > > Am Freitag, dem 06.12.2024 um 16:13 +0000 schrieb Qing Zhao: >> >>> On Dec 6, 2024, at 10:56, Martin Uecker <uec...@tugraz.at> wrote: >>> >>> Am Freitag, dem 06.12.2024 um 14:16 +0000 schrieb Qing Zhao: >>>> > > ... > >>>>> >>>>> I think the relevant scenario is where you assign the struct and >>>>> not a pointer to the struct, i.e. something like the following: >>>>> >>>>> #include "builtin-object-size-common.h" >>>>> >>>>> struct annotated { >>>>> int b; >>>>> int *c __attribute__ ((counted_by (b))); >>>>> }; >>>>> >>>>> struct annotated __attribute__((__noinline__)) setup (int attr_count) >>>>> { >>>>> struct annotated p_array_annotated; >>>>> p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count); >>>>> p_array_annotated.b = attr_count; >>>>> >>>>> return p_array_annotated; >>>>> } >>>>> >>>>> >>>>> int main(int argc, char *argv[]) >>>>> { >>>>> struct annotated x = setup (10); >>>>> int *p = x.c; >>>>> x = setup (20); >>>>> EXPECT(__builtin_dynamic_object_size (p, 1), 10 * sizeof (int)); >>>>> EXPECT(__builtin_dynamic_object_size (x.c, 1), 20 * sizeof (int)); >>>>> DONE (); >>>>> } >>>>> >>>> >>>> With the above testing case, my current implementation based on >>>> .ACCESS_WITH_SIZE succeed without any issue. -:) >>>> The design of .ACCESS_WITH_SIZE already resolved this issue. >>> >>> Ok, thanks! But I am a bit confused, because it seems it behaves >>> this way also for FAMs >>> >>> https://godbolt.org/z/64a6z4cna >> >> The behavior of the above testing case is exactly the additional feature we >> provided for counted_by attribute for FAM: >> >> ===== >> One important feature of the attribute is, a reference to the >> flexible array member field uses the latest value assigned to the >> field that represents the number of the elements before that >> reference. For example, >> >> p->count = val1; >> p->array[20] = 0; // ref1 to p->array >> p->count = val2; >> p->array[30] = 0; // ref2 to p->array >> >> in the above, 'ref1' uses 'val1' as the number of the elements in >> 'p->array', and 'ref2' uses 'val2' as the number of elements in >> 'p->array’. >> ===== >> >> So, it’s the correct behavior for the counted_by attribute for FAM based on >> our previous discussion and agreement. > > If it is indeed that the value of p->count last stored before p->array is > *referenced* which counts, then everything is well.
Yes, For FAM, every “reference” to p->array will be converted as a call to (*.ACCESS_WITH_SIZE (p->array, &p->count, …)) The count value for p->array is *(&p->count), which is guaranteed to be the last stored value of the address of p->count before the current reference to p->array. Similarly, for the pointer array, every “reference” to p->pa will be converted as a call to .ACCESS_WITH_SIZE(p->pa, &p->count…). The count value of the pointer array p->pa is *(&p->count), which is also guaranteed to be the last stored value of the address of p->count before the current reference to p->pa. > Somehow I thought for FAMs it is the value p->count last stored before > p->array is *accessed* (possibly indirectly via another pointer). Probably > it was just me being confused. > >> >> However, as you pointed out, when the “counted_by” attribute is extended to >> the pointer field, this feature will be problematic. >> And we need to add the following additional new requirement for the >> “counted_by” attribute of pointer field: >> >> p->count and p->array can only be changed by changing the whole structure >> at the same time. > > Actually, I am then not even sure we need this requirement. My point was only > that > setting the whole structure at the time should work correctly, i.e. without > changing > the bounds for old pointers which were stored in the struct previously. With > the > semantics above it seems this case also works automatically. For pointer field with counted_by attribute, if the p->count and p->pa are not set together when changing the whole structure, then for example: struct annotated { int b; int *c __attribute__ ((counted_by (b))); }; /* note, this routine only allocate the space for the pointer array field, but does NOT set the counted_by field. */ struct annotated __attribute__((__noinline__)) setup (int attr_count) { struct annotated p_array_annotated; p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count); return p_array_annotated; } int main(int argc, char *argv[]) { struct annotated x = setup (10); x.b = 10; /* the counted_by is set here. */ int *p = x.c; /* x.c’s count should be 10, which is correct. */ x = setup (20); __builtin_dynamic_object_size (x.c, 1); /* x.c’s count now should be 20, but it’s not set yet, the object size is unknown at this moment. Shall we ask the user to always set the counted_by value when the corresponding pointer is changed? */ } thanks. Qing > > Martin > >> >> So for a structure that includes a pointer field with a counted_by >> attribute, the p->count and p->array must be updated at the same time by >> changing the whole structure, therefore the testing case will not be valid >> for pointer field, we MUST change it as the following to make it valid for >> pointer field with counted_by attribute: >> >> int main(int argc, char *argv[]) >> { >> struct annotated *x = setup(10); >> int *p = x->c; >> x = setup(5); >> printf("%d\n", (int)__builtin_dynamic_object_size (p, 1)); >> printf("%d\n", (int)__builtin_dynamic_object_size (x->c, 1)); >> exit(0); >> } >> >> >> Hope this is clear this time -:). > > >> >> Qing >>> >>> and I thought this was changed, i.e. so that the bounds >>> track the current value of b for this case. But apparently >>> I was mistaken. I am fine with the behavior as shown here. >>> >>> Martin >>> >>>> >>>> Qing >>>>> Martin >>>>> >>>>> >>>>> >>>> >>> >>> -- >>> Univ.-Prof. Dr. rer. nat. Martin Uecker >>> Graz University of Technology >>> Institute of Biomedical Imaging