Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #20494 > unrolled thread
| Started by | arnuld <sunrise@invalid.address> |
|---|---|
| First post | 2012-05-08 08:09 +0000 |
| Last post | 2012-05-11 00:39 -0700 |
| Articles | 19 on this page of 39 — 13 participants |
Back to article view | Back to comp.lang.c
Remving an element from Queue arnuld <sunrise@invalid.address> - 2012-05-08 08:09 +0000
Re: Remving an element from Queue Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-05-08 08:01 -0400
Re: Remving an element from Queue arnuld <sunrise@invalid.address> - 2012-05-09 05:43 +0000
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-08 23:21 -0700
Re: Remving an element from Queue arnuld <sunrise@invalid.address> - 2012-05-09 09:27 +0000
Re: Remving an element from Queue James Kuyper <jameskuyper@verizon.net> - 2012-05-09 07:54 -0400
Re: Remving an element from Queue arnuld <sunrise@invalid.address> - 2012-05-09 13:18 +0000
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-09 10:59 -0700
Re: Remving an element from Queue arnuld <arnuld.mizong@gmail.com> - 2012-05-10 05:26 -0700
Re: Remving an element from Queue nick_keighley_nospam@hotmail.com - 2012-05-11 00:11 -0700
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-14 15:53 -0700
Re: Remving an element from Queue lawrence.jones@siemens.com - 2012-05-15 17:42 -0400
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-15 16:40 -0700
Re: Remving an element from Queue James Kuyper <jameskuyper@verizon.net> - 2012-05-15 23:03 -0400
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-15 20:38 -0700
Re: Remving an element from Queue Jens Gustedt <jens.gustedt@loria.fr> - 2012-05-16 08:09 +0200
Re: Remving an element from Queue James Kuyper <jameskuyper@verizon.net> - 2012-05-16 07:18 -0400
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-16 16:30 -0700
Re: Remving an element from Queue James Kuyper <jameskuyper@verizon.net> - 2012-05-17 09:09 -0400
Re: Remving an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-17 11:48 -0700
Re: Removing an element from Queue James Kuyper <jameskuyper@verizon.net> - 2012-05-17 15:38 -0400
Re: Removing an element from Queue Barry Schwarz <schwarzb@dqel.com> - 2012-05-17 15:21 -0700
Re: Removing an element from Queue James Kuyper <jameskuyper@verizon.net> - 2012-05-17 19:08 -0400
Re: Removing an element from Queue Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-19 09:05 -0700
Re: Removing an element from Queue lawrence.jones@siemens.com - 2012-05-20 15:10 -0400
Re: Removing an element from Queue Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-21 09:00 -0700
Re: Remving an element from Queue Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-19 08:49 -0700
Re: Remving an element from Queue Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-17 12:36 -0700
Re: Remving an element from Queue nick_keighley_nospam@hotmail.com - 2012-05-08 05:09 -0700
Re: Remving an element from Queue "BartC" <bc@freeuk.com> - 2012-05-08 14:03 +0100
Re: Remving an element from Queue nick_keighley_nospam@hotmail.com - 2012-05-09 00:01 -0700
Re: Remving an element from Queue nick_keighley_nospam@hotmail.com - 2012-05-09 00:03 -0700
Re: Remving an element from Queue "BartC" <bc@freeuk.com> - 2012-05-09 10:37 +0100
Re: Remving an element from Queue nick_keighley_nospam@hotmail.com - 2012-05-09 03:05 -0700
Re: Remving an element from Queue arnuld <sunrise@invalid.address> - 2012-05-09 09:44 +0000
Re: Remving an element from Queue Mark Bluemel <mark.bluemel@googlemail.com> - 2012-05-08 06:07 -0700
Re: Remving an element from Queue Mark Bluemel <mark.bluemel@googlemail.com> - 2012-05-08 06:35 -0700
Re: Remving an element from Queue Johann Klammer <klammerj@NOSPAM.a1.net> - 2012-05-08 20:50 +0200
Re: Remving an element from Queue 88888 Dihedral <dihedral88888@googlemail.com> - 2012-05-11 00:39 -0700
Page 2 of 2 — ← Prev page 1 [2]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-05-17 15:38 -0400 |
| Subject | Re: Removing an element from Queue |
| Message-ID | <4FB553D2.1060405@verizon.net> |
| In reply to | #20925 |
[Note: corrected typo in Subject: header]
On 05/17/2012 02:48 PM, Barry Schwarz wrote:
> On Thu, 17 May 2012 09:09:12 -0400, James Kuyper
> <jameskuyper@verizon.net> wrote:
>
>> On 05/16/2012 07:30 PM, Barry Schwarz wrote:
>>> On Wed, 16 May 2012 07:18:35 -0400, James Kuyper
>>> <jameskuyper@verizon.net> wrote:
>>>
>>>> On 05/15/2012 11:38 PM, Barry Schwarz wrote:
>>>>> On Tue, 15 May 2012 23:03:39 -0400, James Kuyper
>>>>> <jameskuyper@verizon.net> wrote:
>>>> ...
>>>>>> calloc(a,b) must either return a pointer to enough memory to store 'a'
>>>>>> objects, each of size 'b' bytes, or a null pointer. If the mathematical
>>>>>> product of a*b is greater than SIZE_MAX, then (size_t)(a*b) bytes will
>>>>>> not be sufficient to meet that requirement - but the requirement still
>>>>>> holds. Therefore, calloc(a,b) must either return a null pointer, or
>>>>>> allocate sufficient memory by some mechanism other than malloc(a*b).
>>>>
>>>> ...
>>>>> array. size_t must be able to hold the size in bytes of the largest
>>>>> possible object, including aggregates such as arrays.
>>>>
>>>> Citation, please?
>>>
>>> K&R II, page 135, a stand-alone unindented paragraph approximately 1/3
>>> of the way down the page: "C provides a compile-time unary operator
>>> called sizeof that can be used to compute the size of any object."
>>>
>>
>> K&R II is not authoritative. The C standard is. K&R II often says things
>> less precisely than the standard.
...
>> Also note that the words you cite from K&R II are not, in themselves,
>> sufficient to support your position. "can be used to compute" doesn't
>> require that the computation be carried out using size_t. If it were in
>
> Regardless of how the computation is carried out, the result must fit
> in a size_t.
Citation, please?
>> fact an authoritative requirement, it would not impose a constraint on
>> SIZE_MAX; it only indirectly constrains either UINTMAX_MAX or LDBL_MAX,
>> whichever is larger. For example:
>
> There is no requirement that size_t be the widest possible unsigned
> type. ...
Agreed.
> ... Surely SIZE_MAX cannot exceed UINTMAX_MAX. ...
Agreed.
> ... I don't understand
> how UINTMAX_MAX enters into this discussion.
Because uintmax_t and long double are the types whose limits determine
what "... sizeof ... can be used to compute ...", not size_t. That's
because the term "compute" is sufficiently vague to allow for a sizeof
expression that is no more than a sub-expression of an enclosing
expression with a result that is of some type other than size_t. The
maximum value that can be represented by such an enclosing expression is
either UINTMAX_MAX or LDBL_MAX, whichever is larger (almost certainly
LDBL_MAX). As long as the size can be correctly computed in one of those
types, with the sizeof operator playing some role somewhere in the
computation, then a hypothetical requirement that "... sizeof ... can be
used to compute the size of any object." would be satisfied.
>> char (*)p[SIZE_MAX] = calloc(2, SIZE_MAX);
>> long double size = 2.0L*sizeof *p;
>>
>> In that code, sizeof was indeed used to calculate the size of the object
>> (unless calloc() failed, in which case there is no object, but the size
>> calculation is unaffected by that fact).
>
> While it is not very likely, it is possible for SIZE_MAX to exceed
> LDBL_MAX (1E37 bytes is a large object and size_t would need to be in
> excess of 120 bits). In that case, the implicit conversion in your
> multiplication invokes undefined behavior (6.3.1.4-2). ...
For a hypothetical future version of the standard where there was, in
fact, a requirement that "... sizeof ... can be used to compute the size
of any object.", the existence of such a requirement would imply that a
conforming implementation of C where calloc(2,SIZE_MAX) returns a
non-null pointer must have either UINTMAX_MAX OR LDBL_MAX >= the size of
the object created by that call. Therefore, you could write:
if(p)
{
#if UINTMAX_MAX/2 >= SIZE_MAX
uintmax_t size = 2LL * sizeof *p;
#else
long double size = 2.0L * sizeof *p;
#endif
// do something with size.
}
...
> My only assertion was that since the result of calloc(a,b) is to be
> treated as a single array, calloc should fail if a*b mathematically
> exceeds SIZE_MAX.
An assertion for which you've provided no citations from the standard,
nor any arguments based upon such citations. Even the citation you have
provided from K&R II fails to specify any such requirement.
> ... I didn't address whether SIZE_MAX could be
> converted to a real floating type or any other integer type (though it
> seems obvious it should be convertible to a uintmax_t).
I wasn't talking about converting the size to another type; I was
talking about calculating the size in another type, because SIZE_MAX was
too small to be used for such calculations. Because such calculations
can be performed, a requirement that the computation be possible does
not greatly constrain the value of SIZE_MAX.
That was really intended as a kind of joke. Perhaps I should have
inserted a smiley, but I thought that it was neither sufficiently funny
nor sufficiently obscure to require a smiley. I guess I was wrong on
that second part. All I was trying to do was point out that "... can be
used to compute ..." is too vague a phrase to be used in a specification
that would mean what you wanted it to mean.
> The wording is unchanged in n1570.
The wording of what? All of the citations from the standard so far have
been made by me, and none of them are worded in such a way as to
conflict with the implementation I described.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2012-05-17 15:21 -0700 |
| Subject | Re: Removing an element from Queue |
| Message-ID | <kusar7tot63gvqshh4b0iusmvievula6di@4ax.com> |
| In reply to | #20928 |
On Thu, 17 May 2012 15:38:58 -0400, James Kuyper <jameskuyper@verizon.net> wrote: >[Note: corrected typo in Subject: header] > >On 05/17/2012 02:48 PM, Barry Schwarz wrote: >> On Thu, 17 May 2012 09:09:12 -0400, James Kuyper >> <jameskuyper@verizon.net> wrote: >> >>> On 05/16/2012 07:30 PM, Barry Schwarz wrote: >>>> On Wed, 16 May 2012 07:18:35 -0400, James Kuyper >>>> <jameskuyper@verizon.net> wrote: >>>> >>>>> On 05/15/2012 11:38 PM, Barry Schwarz wrote: >>>>>> On Tue, 15 May 2012 23:03:39 -0400, James Kuyper >>>>>> <jameskuyper@verizon.net> wrote: >>>>> ... >>>>>>> calloc(a,b) must either return a pointer to enough memory to store 'a' >>>>>>> objects, each of size 'b' bytes, or a null pointer. If the mathematical >>>>>>> product of a*b is greater than SIZE_MAX, then (size_t)(a*b) bytes will >>>>>>> not be sufficient to meet that requirement - but the requirement still >>>>>>> holds. Therefore, calloc(a,b) must either return a null pointer, or >>>>>>> allocate sufficient memory by some mechanism other than malloc(a*b). >>>>> >>>>> ... >>>>>> array. size_t must be able to hold the size in bytes of the largest >>>>>> possible object, including aggregates such as arrays. >>>>> >>>>> Citation, please? >>>> >>>> K&R II, page 135, a stand-alone unindented paragraph approximately 1/3 >>>> of the way down the page: "C provides a compile-time unary operator >>>> called sizeof that can be used to compute the size of any object." >>>> >>> >>> K&R II is not authoritative. The C standard is. K&R II often says things >>> less precisely than the standard. >... >>> Also note that the words you cite from K&R II are not, in themselves, >>> sufficient to support your position. "can be used to compute" doesn't >>> require that the computation be carried out using size_t. If it were in >> >> Regardless of how the computation is carried out, the result must fit >> in a size_t. > >Citation, please? Unless I misread your original response, which has been snipped beyond recognition above, the result in question was the evaluation of the sizeof operator. Is there some debate about the type of this evaluation? snip >> My only assertion was that since the result of calloc(a,b) is to be >> treated as a single array, calloc should fail if a*b mathematically >> exceeds SIZE_MAX. > >An assertion for which you've provided no citations from the standard, >nor any arguments based upon such citations. Even the citation you have >provided from K&R II fails to specify any such requirement. I'll agree to disagree. >> The wording is unchanged in n1570. > >The wording of what? All of the citations from the standard so far have >been made by me, and none of them are worded in such a way as to >conflict with the implementation I described. So my quote from 7.20.3.1 wasn't from the standard? OK, I confess. I actually copied it from n1256. We can disagree on whether I'm interpreting it correctly but I did provide it. You even quoted it back to me in your message of 15 May at 2303Z. Looking at snipped quotes in a response is not a good way to remember who said what :-) -- Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-05-17 19:08 -0400 |
| Subject | Re: Removing an element from Queue |
| Message-ID | <4FB584DA.7040509@verizon.net> |
| In reply to | #20952 |
On 05/17/2012 06:21 PM, Barry Schwarz wrote: > On Thu, 17 May 2012 15:38:58 -0400, James Kuyper > <jameskuyper@verizon.net> wrote: > >> [Note: corrected typo in Subject: header] >> >> On 05/17/2012 02:48 PM, Barry Schwarz wrote: >>> On Thu, 17 May 2012 09:09:12 -0400, James Kuyper >>> <jameskuyper@verizon.net> wrote: >>> >>>> On 05/16/2012 07:30 PM, Barry Schwarz wrote: >>>>> On Wed, 16 May 2012 07:18:35 -0400, James Kuyper >>>>> <jameskuyper@verizon.net> wrote: >>>>> >>>>>> On 05/15/2012 11:38 PM, Barry Schwarz wrote: >>>>>>> On Tue, 15 May 2012 23:03:39 -0400, James Kuyper >>>>>>> <jameskuyper@verizon.net> wrote: >>>>>> ... >>>>>>>> calloc(a,b) must either return a pointer to enough memory to store 'a' >>>>>>>> objects, each of size 'b' bytes, or a null pointer. If the mathematical >>>>>>>> product of a*b is greater than SIZE_MAX, then (size_t)(a*b) bytes will >>>>>>>> not be sufficient to meet that requirement - but the requirement still >>>>>>>> holds. Therefore, calloc(a,b) must either return a null pointer, or >>>>>>>> allocate sufficient memory by some mechanism other than malloc(a*b). >>>>>> >>>>>> ... >>>>>>> array. size_t must be able to hold the size in bytes of the largest >>>>>>> possible object, including aggregates such as arrays. >>>>>> >>>>>> Citation, please? >>>>> >>>>> K&R II, page 135, a stand-alone unindented paragraph approximately 1/3 >>>>> of the way down the page: "C provides a compile-time unary operator >>>>> called sizeof that can be used to compute the size of any object." >>>>> >>>> >>>> K&R II is not authoritative. The C standard is. K&R II often says things >>>> less precisely than the standard. >> ... >>>> Also note that the words you cite from K&R II are not, in themselves, >>>> sufficient to support your position. "can be used to compute" doesn't >>>> require that the computation be carried out using size_t. If it were in >>> >>> Regardless of how the computation is carried out, the result must fit >>> in a size_t. >> >> Citation, please? > > Unless I misread your original response, which has been snipped beyond > recognition above, the result in question was the evaluation of the > sizeof operator. ... No, the result in question was the calculation of "... the size of any object." The text saying so was yours, not mine, and it has survived all snipping. > ... Is there some debate about the type of this > evaluation? No, there's a debate about whether that type is required to be capable of holding "the size of any object". I contend it's only required to hold the size of types, whether or not there's an object of that type. Passing a type to sizeof, either directly or through an expression of that type, whose size cannot be represented in size_t, renders the behavior undefined by reason of a lack of definition (or more precisely, by reason of an internally contradictory definition of the behavior). >>> My only assertion was that since the result of calloc(a,b) is to be >>> treated as a single array, calloc should fail if a*b mathematically >>> exceeds SIZE_MAX. >> >> An assertion for which you've provided no citations from the standard, >> nor any arguments based upon such citations. Even the citation you have >> provided from K&R II fails to specify any such requirement. > > I'll agree to disagree. I'd prefer an explanation of your disagreement, over a bald statement of it. >>> The wording is unchanged in n1570. >> >> The wording of what? All of the citations from the standard so far have >> been made by me, and none of them are worded in such a way as to >> conflict with the implementation I described. > > So my quote from 7.20.3.1 wasn't from the standard? Sorry, I missed the fact that you did cite that section, probably due to it's lack of relevance. The implementation I described conforms to the requirements of 7.20.3.1; the (unspecified) value of SIZE_MAX is, indeed, as required by 7.20.3.1, "the limit of size_t". What I've repeatedly challenged you to provide is one or more citations that say, directly or indirectly, that SIZE_MAX is the limit on the size of objects. If they say it only indirectly, they should be accompanied by an argument explaining how that conclusion may be derived from those citations. All you've been doing is saying that this must be the case, without addressing my arguments, or presenting any of your own. I'll give you some help: 7.19p2 describes size_t: "the unsigned integer type of the result of the sizeof operator". It does not describe it as a type with sufficient range to store the size of any object. 6.5.3.4p2 specifies that "The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand". It does not say that arbitrary expressions which have not been passed to sizeof() must have types small enough that sizeof() could express the size of those types. It does say that only the type of the expression is relevant in determining the value yielded by "sizeof expression". Therefore, if "sizeof expression" causes problems with 6.5.3.4p2, the problems are due to the type of the expression, and can be fixed by changing that type; they don't have anything to do with the value of that expression, whether or not it is an lvalue expression referring to an actual object. Those problems can therefore neither be avoided by having calloc() return a null pointer value, nor caused by calloc() returning a non-null pointer value. 6.5.3.4p2 therefore cannot constrain calloc() to return a null pointer. > We can disagree on whether I'm interpreting it correctly but I did > provide it. You even quoted it back to me in your message of 15 May > at 2303Z. Looking at snipped quotes in a response is not a good way > to remember who said what :-) Neither is looking at unsnipped quotes, when they get as long as they would be if I'd failed to snip them.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-19 09:05 -0700 |
| Subject | Re: Removing an element from Queue |
| Message-ID | <kfnbolk2m2s.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20956 |
James Kuyper <jameskuyper@verizon.net> writes: > On 05/17/2012 06:21 PM, Barry Schwarz wrote: >> On Thu, 17 May 2012 15:38:58 -0400, James Kuyper >> <jameskuyper@verizon.net> wrote: >> >>> [Note: corrected typo in Subject: header] >>> >>> On 05/17/2012 02:48 PM, Barry Schwarz wrote: >>>> On Thu, 17 May 2012 09:09:12 -0400, James Kuyper >>>> <jameskuyper@verizon.net> wrote: >>>> >>>>> On 05/16/2012 07:30 PM, Barry Schwarz wrote: >>>>>> On Wed, 16 May 2012 07:18:35 -0400, James Kuyper >>>>>> <jameskuyper@verizon.net> wrote: >>>>>> >>>>>>> On 05/15/2012 11:38 PM, Barry Schwarz wrote: >>>>>>>> On Tue, 15 May 2012 23:03:39 -0400, James Kuyper >>>>>>>> <jameskuyper@verizon.net> wrote: >>>>>>> ... >>>>>>>>> calloc(a,b) must either return a pointer to enough memory to store 'a' >>>>>>>>> objects, each of size 'b' bytes, or a null pointer. If the mathematical >>>>>>>>> product of a*b is greater than SIZE_MAX, then (size_t)(a*b) bytes will >>>>>>>>> not be sufficient to meet that requirement - but the requirement still >>>>>>>>> holds. Therefore, calloc(a,b) must either return a null pointer, or >>>>>>>>> allocate sufficient memory by some mechanism other than malloc(a*b). >>>>>>> >>>>>>> ... >>>>>>>> array. size_t must be able to hold the size in bytes of the largest >>>>>>>> possible object, including aggregates such as arrays. >>>>>>> >>>>>>> Citation, please? >>>>>> >>>>>> K&R II, page 135, a stand-alone unindented paragraph approximately 1/3 >>>>>> of the way down the page: "C provides a compile-time unary operator >>>>>> called sizeof that can be used to compute the size of any object." >>>>>> >>>>> >>>>> K&R II is not authoritative. The C standard is. K&R II often says things >>>>> less precisely than the standard. >>> ... >>>>> Also note that the words you cite from K&R II are not, in themselves, >>>>> sufficient to support your position. "can be used to compute" doesn't >>>>> require that the computation be carried out using size_t. If it were in >>>> >>>> Regardless of how the computation is carried out, the result must fit >>>> in a size_t. >>> >>> Citation, please? >> >> Unless I misread your original response, which has been snipped beyond >> recognition above, the result in question was the evaluation of the >> sizeof operator. ... > > No, the result in question was the calculation of "... the size of any > object." The text saying so was yours, not mine, and it has survived all > snipping. > >> ... Is there some debate about the type of this >> evaluation? > > No, there's a debate about whether that type is required to be capable > of holding "the size of any object". I contend it's only required to > hold the size of types, whether or not there's an object of that type. > Passing a type to sizeof, either directly or through an expression of > that type, whose size cannot be represented in size_t, renders the > behavior undefined Which is it? Does the Standard require sizeof to produce a value that must fit in a size_t, or is the behavior of sizeof undefined in some cases? They can't both be true. I don't see any text in the Standard that requires that the result of doing a sizeof must fit in a size_t, only that the type of the result is size_t. > by reason of a lack of definition (or more precisely, by reason > of an internally contradictory definition of the behavior). Actually the behavior in such cases is explicitly undefined under the provisions 6.5 p5.
[toc] | [prev] | [next] | [standalone]
| From | lawrence.jones@siemens.com |
|---|---|
| Date | 2012-05-20 15:10 -0400 |
| Subject | Re: Removing an element from Queue |
| Message-ID | <k6sn89-cen.ln1@jones.homeip.net> |
| In reply to | #21029 |
Tim Rentsch <txr@alumni.caltech.edu> wrote: > > Which is it? Does the Standard require sizeof to produce a value > that must fit in a size_t, or is the behavior of sizeof undefined in > some cases? They can't both be true. Previous discussions have, I think, reached concensus that there are two valid ways to resolve the apparent contradiction: An implementation is free to disallow declarations (including abstract ones) that would specify a size that is too big to fit in a size_t. An implementation is also free to accept such declarations and declare that the behavior of sizeof is undefined in that case. Both lead to completely consistent readings of the standard and the committee has not felt compelled to bless one over the other. -- Larry Jones What's Santa's definition? How good do you have to be to qualify as good? -- Calvin
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-21 09:00 -0700 |
| Subject | Re: Removing an element from Queue |
| Message-ID | <kfn7gw534ns.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #21076 |
lawrence.jones@siemens.com writes: > Tim Rentsch <txr@alumni.caltech.edu> wrote: >> >> Which is it? Does the Standard require sizeof to produce a value >> that must fit in a size_t, or is the behavior of sizeof undefined in >> some cases? They can't both be true. > > Previous discussions have, I think, reached concensus that there are two > valid ways to resolve the apparent contradiction: An implementation is > free to disallow declarations (including abstract ones) that would > specify a size that is too big to fit in a size_t. An implementation is > also free to accept such declarations and declare that the behavior of > sizeof is undefined in that case. Both lead to completely consistent > readings of the standard and the committee has not felt compelled to > bless one over the other. I would expect that implementations are always free to reject any program that has a type whose size is known to be > 65535, for exceeding a minimum environmental limit, whether sizeof is used or not. Certainly such a program cannot be strictly conforming, as it is reasonable to expect any implementation with SIZE_MAX equal to 65535 normally would reject it. Still, the Standard doesn't require rejection of programs whose types are too large. Moreover, it is not always possible to determine at compile time if the size of a type will exceed SIZE_MAX, because of variable length arrays. If sizeof is used on such a type that is overly large, the result is not in the range of representable values for its type, that is, this would be an /exceptional condition/ as defined in 6.5 p5, and so is explicitly undefined behavior. Ergo I don't think there is any contradiction. The Standard allows but does not require an implementation to reject programs known to have overly large types; any sizeof's done on overly large types that may arise otherwise fall under 6.5 p5, and hence are undefined behavior.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-19 08:49 -0700 |
| Message-ID | <kfnfwaw2msn.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20869 |
Barry Schwarz <schwarzb@dqel.com> writes:
> On Wed, 16 May 2012 07:18:35 -0400, James Kuyper
> <jameskuyper@verizon.net> wrote:
>
>>On 05/15/2012 11:38 PM, Barry Schwarz wrote:
>>> On Tue, 15 May 2012 23:03:39 -0400, James Kuyper
>>> <jameskuyper@verizon.net> wrote:
>>...
>>>> calloc(a,b) must either return a pointer to enough memory to store 'a'
>>>> objects, each of size 'b' bytes, or a null pointer. If the mathematical
>>>> product of a*b is greater than SIZE_MAX, then (size_t)(a*b) bytes will
>>>> not be sufficient to meet that requirement - but the requirement still
>>>> holds. Therefore, calloc(a,b) must either return a null pointer, or
>>>> allocate sufficient memory by some mechanism other than malloc(a*b).
>>
>>...
>>> array. size_t must be able to hold the size in bytes of the largest
>>> possible object, including aggregates such as arrays.
>>
>>Citation, please?
>
> K&R II, page 135, a stand-alone unindented paragraph approximately 1/3
> of the way down the page: "C provides a compile-time unary operator
> called sizeof that can be used to compute the size of any object."
Consider the following conforming program:
#include <stdio.h>
int
main(){
unsigned k;
unsigned long long n;
for( k = 0; k < 20; k++ ){
n = sizeof (char [k][ (size_t)-1 / 17 ]);
printf( "k: %3u n: %40llu\n", k, n );
}
return 0;
}
The type (char [k][ (size_t)-1 / 17 ]) corresponds to what we
might expect from a calling calloc( k, (size_t)-1 / 17 ) , eg,
we might have
char (*a)[(size_t)-1 / 17] = calloc( k, (size_t)-1 / 17 );
and then use a[i][j] to access individual characters of the
allocated memory returned by calloc().
Question: could a conforming implementation define calloc()
in such a way that the allocation
char (*a)[(size_t)-1 / 17] = calloc( k, (size_t)-1 / 17 );
works for k == 100, ie, a non-null pointer is returned, and
the amount of memory allocated is sufficiently large to hold
an array of type (char[k][(size_t)-1 / 17]), and accesses to
the array using
a[i][j]
with 0 <= i < k, and 0 <= j < (size_t)-1 / 17, will all work?
My answer to this question is Yes. And that answer is consistent
with the existence and observed behavior of the conforming program
shown above.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-05-17 12:36 -0700 |
| Message-ID | <kfnr4ui4n2y.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #20844 |
Barry Schwarz <schwarzb@dqel.com> writes: > On Tue, 15 May 2012 23:03:39 -0400, James Kuyper > <jameskuyper@verizon.net> wrote: > >>On 05/15/2012 07:40 PM, Barry Schwarz wrote: >>> On Tue, 15 May 2012 17:42:46 -0400, lawrence.jones@siemens.com wrote: >>> >>>> Barry Schwarz <schwarzb@dqel.com> wrote: >>>>> >>>>> As long as malloc doesn't fail, >>>> >>>> And a*b doesn't overflow, >>>> >>>>> calloc(a,b) = memset(malloc(a*b),0,a*b) >>> >>> Unsigned arithmetic cannot overflow. >>> >>> Given the wording in 7.20.3.1, where the allocated space constitutes a >>> single array, I have no idea what happens when the arithmetic product >>> a*b exceeds the value of SIZE_MAX. ... >> >>calloc(a,b) must either return a pointer to enough memory to store 'a' >>objects, each of size 'b' bytes, or a null pointer. If the mathematical >>product of a*b is greater than SIZE_MAX, then (size_t)(a*b) bytes will >>not be sufficient to meet that requirement - but the requirement still >>holds. Therefore, calloc(a,b) must either return a null pointer, or >>allocate sufficient memory by some mechanism other than malloc(a*b). > > That is not what the standard says - "The calloc function allocates > space for an array of nmemb objects, each of whose size is size. The > space is initialized to all bits zero." Note the additional > requirement that the entire allocated space be considered a single > array. size_t must be able to hold the size in bytes of the largest > possible object, including aggregates such as arrays. [snip] The Standard does not impose such a requirement, either for regular objects or for those dynamically allocated. Certainly it is typically true, and normally implementations enforce it for regular objects whose size is known at compile time, but neither of those conditions is necessary for an implementation to be conforming.
[toc] | [prev] | [next] | [standalone]
| From | nick_keighley_nospam@hotmail.com |
|---|---|
| Date | 2012-05-08 05:09 -0700 |
| Message-ID | <27603720.623.1336478949976.JavaMail.geo-discussion-forums@vbcm9> |
| In reply to | #20494 |
On Tuesday, May 8, 2012 9:09:39 AM UTC+1, arnuld wrote:
> WANTED: Removing all elements matching a particular key from a Queue
> WHAT I GOT: Segfault
> WANTED: Segfaults in removeAllMatches(). I think routine/fucntion is too
> complex to be understood. removeAllMatches(arg1, arg2) is supposed to
> remove all elements from arg1 which match value of arg2.
I don't get any output at all it crashes at the first printQueue() call in main(). The Head and Tail pointers contain crap (0xcdcdcd on a Microsoft system). They contain crap because newQueue() doesn't initialise them.
Why didn't you use a debugger? That's how I found the bug.
<code>
[...]
> struct myQueue
> {
> struct myStruct* head;
> struct myStruct* tail;
> };
[...]
> int main(void)
> {
> struct myQueue* q = newQueue();
> printQueue(q); <--- DIE!
>
> enqueue(q, -1);
[...]
> struct myQueue* newQueue(void)
> {
> struct myQueue* p = malloc(1 * sizeof *p);
> if(NULL == p)
> {
> printf("Out of Memory\n");
> exit(EXIT_FAILURE);
> }
>
> return p;
what are head and tail at this point?
> }
>
>
> void printQueue(struct myQueue* q)
> {
> if(q)
> {
> struct myStruct* p = q->head;
oops!
> for(; p; p = p->next) printStruct(p);
> printf("-----------------------------------------\n");
> }
> }
</code>
>
> ======================== OUTPUT ==========================
> [arnuld@dune C]$ gcc -ansi -pedantic -Wall -Wextra Queue.c
> [arnuld@dune C]$ ./a.out
> -----------------------------------------
> Empty Queue, Adding first element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> title: -1
> title: 100
> title: 38
> title: 100
> title: 38
> title: 9
> title: 100
> -----------------------------------------
> Segmentation fault
> [arnuld@dune C]$
you could tidy things up by factoring out your queue check code that appears in at least three places
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-05-08 14:03 +0100 |
| Message-ID | <job5k5$9rd$1@dont-email.me> |
| In reply to | #20503 |
<nick_keighley_nospam@hotmail.com> wrote in message news:27603720.623.1336478949976.JavaMail.geo-discussion-forums@vbcm9... > On Tuesday, May 8, 2012 9:09:39 AM UTC+1, arnuld wrote: > >> WANTED: Removing all elements matching a particular key from a Queue >> WHAT I GOT: Segfault >> WANTED: Segfaults in removeAllMatches(). I think routine/fucntion is too >> complex to be understood. removeAllMatches(arg1, arg2) is supposed to >> remove all elements from arg1 which match value of arg2. > > I don't get any output at all it crashes at the first printQueue() call in > main(). The Head and Tail pointers contain crap (0xcdcdcd on a Microsoft > system). They contain crap because newQueue() doesn't initialise them. > Why didn't you use a debugger? That's how I found the bug. Mine just prints forever on printQueue(). Looking at newQueue() instantly reveals the problem. No need for any debugger. And what exactly did it say anyway? -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | nick_keighley_nospam@hotmail.com |
|---|---|
| Date | 2012-05-09 00:01 -0700 |
| Message-ID | <10610081.157.1336546884984.JavaMail.geo-discussion-forums@vbyb13> |
| In reply to | #20505 |
On Tuesday, May 8, 2012 2:03:48 PM UTC+1, Bart wrote: > <nick_keighley_nospam@hotmail.com> wrote in message > news:27603720.623.1336478949976.JavaMail.geo-discussion-forums@vbcm9... > > On Tuesday, May 8, 2012 9:09:39 AM UTC+1, arnuld wrote: > > > >> WANTED: Removing all elements matching a particular key from a Queue > >> WHAT I GOT: Segfault > >> WANTED: Segfaults in removeAllMatches(). I think routine/fucntion is too > >> complex to be understood. removeAllMatches(arg1, arg2) is supposed to > >> remove all elements from arg1 which match value of arg2. > > > > I don't get any output at all it crashes at the first printQueue() call in > > main(). The Head and Tail pointers contain crap (0xcdcdcd on a Microsoft > > system). They contain crap because newQueue() doesn't initialise them. > > > Why didn't you use a debugger? That's how I found the bug. > > Mine just prints forever on printQueue(). Looking at newQueue() instantly > reveals the problem. and main() > No need for any debugger. And what exactly did it say anyway? well the program has Undefined Behaviour so the question isn't really meaningful. Visual C++ gives:- "Unhandled exception at 0x00411cc9 in quick.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd." The debugger shows it crashed in printStruct() and p has an insane value.
[toc] | [prev] | [next] | [standalone]
| From | nick_keighley_nospam@hotmail.com |
|---|---|
| Date | 2012-05-09 00:03 -0700 |
| Message-ID | <17230148.361.1336546987566.JavaMail.geo-discussion-forums@vbcm9> |
| In reply to | #20505 |
On Tuesday, May 8, 2012 2:03:48 PM UTC+1, Bart wrote: > <nick_keighley_nospam@hotmail.com> wrote in message > news:27603720.623.1336478949976.JavaMail.geo-discussion-forums@vbcm9... > > On Tuesday, May 8, 2012 9:09:39 AM UTC+1, arnuld wrote: > > > >> WANTED: Removing all elements matching a particular key from a Queue > >> WHAT I GOT: Segfault > >> WANTED: Segfaults in removeAllMatches(). I think routine/fucntion is too > >> complex to be understood. removeAllMatches(arg1, arg2) is supposed to > >> remove all elements from arg1 which match value of arg2. > > > > I don't get any output at all it crashes at the first printQueue() call in > > main(). The Head and Tail pointers contain crap (0xcdcdcd on a Microsoft > > system). They contain crap because newQueue() doesn't initialise them. > > > Why didn't you use a debugger? That's how I found the bug. > > Mine just prints forever on printQueue(). Looking at newQueue() instantly > reveals the problem. and main() > No need for any debugger. And what exactly did it say anyway? well the program has Undefined Behaviour so the question isn't really meaningful. Visual C++ gives:- "Unhandled exception at 0x00411cc9 in quick.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd." The debugger shows it crashed in printStruct() and p has an insane value.
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-05-09 10:37 +0100 |
| Message-ID | <joddtv$r8v$1@dont-email.me> |
| In reply to | #20538 |
<nick_keighley_nospam@hotmail.com> wrote in message news:17230148.361.1336546987566.JavaMail.geo-discussion-forums@vbcm9... > On Tuesday, May 8, 2012 2:03:48 PM UTC+1, Bart wrote: >> <nick_keighley_nospam@hotmail.com> wrote in message >> > Why didn't you use a debugger? That's how I found the bug. >> >> Mine just prints forever on printQueue(). Looking at newQueue() instantly >> reveals the problem. > > and main() > >> No need for any debugger. And what exactly did it say anyway? > > well the program has Undefined Behaviour so the question isn't really > meaningful. Visual C++ gives:- > > "Unhandled exception at 0x00411cc9 in quick.exe: 0xC0000005: Access > violation reading location 0xcdcdcdcd." > > The debugger shows it crashed in printStruct() and p has an insane value. As I said, when I tried it under one compiler, it just looped forever p;rinting the same sequence of 3 or 4 values, so p (ie. q->head) presumably had a sensible enough value. Debuggers have their uses but are probably overkill for an obvious logic error within the first dozen lines of execution! When a program goes wrong a few billion statements from the start, because of some unrelated code a billion or two statements back in a totally different part, then it might be time to wheel it out (and even then I'm not sure how they could help). -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | nick_keighley_nospam@hotmail.com |
|---|---|
| Date | 2012-05-09 03:05 -0700 |
| Message-ID | <337629.1991.1336557915938.JavaMail.geo-discussion-forums@vbqq1> |
| In reply to | #20541 |
On Wednesday, May 9, 2012 10:37:38 AM UTC+1, Bart wrote: > <nick_keighley_nospam@hotmail.com> wrote in message > news:17230148.361.1336546987566.JavaMail.geo-discussion-forums@vbcm9... > > On Tuesday, May 8, 2012 2:03:48 PM UTC+1, Bart wrote: > >> <nick_keighley_nospam@hotmail.com> wrote in message > >> > Why didn't you use a debugger? That's how I found the bug. <snip> > >> No need for any debugger. And what exactly did it say anyway? > > > > well the program has Undefined Behaviour so the question isn't really > > meaningful. Visual C++ gives:- > > > > "Unhandled exception at 0x00411cc9 in quick.exe: 0xC0000005: Access > > violation reading location 0xcdcdcdcd." > > > > The debugger shows it crashed in printStruct() and p has an insane value. > > As I said, when I tried it under one compiler, it just looped forever > p;rinting the same sequence of 3 or 4 values, so p (ie. q->head) presumably > had a sensible enough value. > > Debuggers have their uses but are probably overkill for an obvious logic > error within the first dozen lines of execution! and how would I know the crash was going to occur within a few dozen lines of startup? > When a program goes wrong a few billion statements from the start, because > of some unrelated code a billion or two statements back in a totally > different part, then it might be time to wheel it out (and even then I'm not > sure how they could help). whatever. I judged running under a debugger was a quicker way to find the bug than ploughing through lots of source code. It so happened it pin-pointed the bug almost instantly.
[toc] | [prev] | [next] | [standalone]
| From | arnuld <sunrise@invalid.address> |
|---|---|
| Date | 2012-05-09 09:44 +0000 |
| Message-ID | <4faa3c85$0$282$14726298@news.sunsite.dk> |
| In reply to | #20503 |
> On Tue, 08 May 2012 05:09:09 -0700, nick_keighley_nospam wrote: > ..SNIP... > you could tidy things up by factoring out your queue check code that > appears in at least three places you are right. I did that and now after reading the analysis from Barry Schwarz I can see that head/tail pointing at wrong places, so I should make a check for that too ? No, unlike earlier now I think those checks will not save these programming errors I am making. I better set pointers right rather than spending my typing-energy to avoid/find errors. -- arnuld http://LispMachine.Wordpress.com
[toc] | [prev] | [next] | [standalone]
| From | Mark Bluemel <mark.bluemel@googlemail.com> |
|---|---|
| Date | 2012-05-08 06:07 -0700 |
| Message-ID | <3741deef-a4e7-441b-878a-67598870fdd8@m10g2000vbb.googlegroups.com> |
| In reply to | #20494 |
On May 8, 9:09 am, arnuld <sunr...@invalid.address> wrote:
> WANTED: Removing all elements matching a particular key from a Queue
> WHAT I GOT: Segfault
> WANTED: Segfaults in removeAllMatches(). I think routine/fucntion is too
> complex to be understood. removeAllMatches(arg1, arg2) is supposed to
> remove all elements from arg1 which match value of arg2.
>
> #include <stdio.h>
> #include <stdlib.h>
>
> struct myStruct
> {
> int num;
> struct myStruct* next;
>
> };
>
> struct myQueue
> {
> struct myStruct* head;
> struct myStruct* tail;
>
> };
>
> int enqueue(struct myQueue* q, int n);
> int dequeue(struct myQueue* q);
>
> struct myQueue* newQueue(void);
> void makeNull(struct myQueue* q);
> void removeAllMatches(struct myQueue* q, const int num);
>
> void printQueue(struct myQueue* q);
> void printStruct(struct myStruct* p);
>
> int main(void)
> {
> struct myQueue* q = newQueue();
> printQueue(q);
>
> enqueue(q, -1);
> enqueue(q, 100);
> enqueue(q, 38);
> enqueue(q, 100);
> enqueue(q, 38);
> enqueue(q, 9);
> enqueue(q, 100);
> printQueue(q);
>
> removeAllMatches(q, 100);
> printQueue(q);
> /* makeNull(q);
> printQueue(q); */
> free(q);
> q = NULL;
>
> return 0;
>
> }
>
> int enqueue(struct myQueue* q, int n)
> {
> int ret;
> if(NULL == q)
> {
> printf("Invalid Args\n");
> ret = -1;
> }
> else
> {
> struct myStruct* p = malloc(1 * sizeof *p);
> if(NULL == p)
> {
> printf("Out of memory\n");
> exit(EXIT_FAILURE);
> }
>
> p->num = n;
> p->next = NULL;
> if(NULL == q->tail && NULL == q->head)
> {
> printf("Empty Queue, Adding first element\n");
> q->head = q->tail = p;
> ret = 0;
> }
> else if(NULL == q->tail || NULL == q->head)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> free(p);
> ret = 1;
> }
> else
> {
> printf("Adding Element\n");
> q->tail->next = p;
> q->tail = p;
> ret = 0;
> }
> }
>
> return ret;
>
> }
>
> int dequeue(struct myQueue* q)
> {
> int ret = -1;
> if(NULL == q)
> {
> printf("Invalid Args\n");
> ret = -1;
> }
> else
> {
> struct myStruct* h;
> if(NULL == q->head && NULL == q->tail)
> {
> printf("Queue is already empty\n");
> ret = 0;
> }
> else if(NULL == q->head || NULL == q->tail)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> ret = 1;
> }
> else
> {
> h = q->head;
> q->head = q->head->next;
> free(h);
> if(NULL == q->head)
> {
> printf("Removing Last element left\n");
> q->head = q->tail = NULL;
> }
> else
> {
> printf("Removing Some element\n");
> }
> ret = 0;
> }
> }
>
> return ret;
>
> }
>
> /* Added many months later */
> void removeAllMatches(struct myQueue* q, const int num)
> {
> if(NULL == q)
> {
> printf("Invalid Args\n");
> return;
> }
>
> if(NULL == q->head && NULL == q->tail)
> {
> printf("Queue is already empty\n");
> }
> else if(NULL == q->head || NULL == q->tail)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> exit(EXIT_FAILURE);
> }
> else
> {
> struct myStruct *p, *d, *h;
> p = d = h = NULL;
> for(h = q->head; h; h = h->next)
> {
> d = h;
> if(num == d->num)
> {
> if(num == q->head->num )
> {
> q->head = q->head->next;
> }
>
> if(num == q->tail->num)
> {
> q->tail = q->tail->next;
> }
>
> if(p)
> {
> p->next = h->next;
> }
> free(d);
> }
> else
> {
> p = h;
> }
> }
>
> }
>
> }
>
> void makeNull(struct myQueue* q)
> {
> if(q)
> {
> while(q->head) dequeue(q);
> }
>
> }
>
> struct myQueue* newQueue(void)
> {
> struct myQueue* p = malloc(1 * sizeof *p);
> if(NULL == p)
> {
> printf("Out of Memory\n");
> exit(EXIT_FAILURE);
> }
>
> return p;
>
> }
>
> void printQueue(struct myQueue* q)
> {
> if(q)
> {
> struct myStruct* p = q->head;
> for(; p; p = p->next) printStruct(p);
> printf("-----------------------------------------\n");
> }
>
> }
>
> void printStruct(struct myStruct* p)
> {
> if(p)
> {
> printf("title: %d\n", p->num);
> }
>
> }
>
> ======================== OUTPUT ==========================
> [arnuld@dune C]$ gcc -ansi -pedantic -Wall -Wextra Queue.c
> [arnuld@dune C]$ ./a.out
> -----------------------------------------
> Empty Queue, Adding first element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> title: -1
> title: 100
> title: 38
> title: 100
> title: 38
> title: 9
> title: 100
> -----------------------------------------
> Segmentation fault
> [arnuld@dune C]$
>
> --
> arnuldhttp://LispMachine.Wordpress.com
You need to stop coding and start thinking...
I don't know what's wrong with your code (though I have strong
suspicions about the code which tries to do some special casing for
start and end of list), but if I could be bothered to investigate I'd
probably do the old "paper computer" exercise...
On a largish sheet of paper I'd draw the structure of my linked list
at the point that the removeAll function was invoked, with a box
representing each entry of the list, with the forward and back
pointers and the value stored.
I'd then draw boxes for p, d and h (horrid names for variables) and
walk through the code updating all the boxes as I went.
I don't know why you keep repeating your checking code rather than
extracting it to a "sanity_check" function. I also don't know why you
don't have a function for "remove the current entry" from the list,
but you seem to be making a big deal out of a fairly small exercise.
[toc] | [prev] | [next] | [standalone]
| From | Mark Bluemel <mark.bluemel@googlemail.com> |
|---|---|
| Date | 2012-05-08 06:35 -0700 |
| Message-ID | <9d86999b-9499-4e42-b27f-b0cc9e0dae0f@i8g2000vbm.googlegroups.com> |
| In reply to | #20494 |
On May 8, 9:09 am, arnuld <sunr...@invalid.address> wrote:
> void removeAllMatches(struct myQueue* q, const int num)
> {
...
> struct myStruct *p, *d, *h;
> p = d = h = NULL;
> for(h = q->head; h; h = h->next)
> {
> d = h;
> if(num == d->num)
> {
> if(num == q->head->num )
> {
> q->head = q->head->next;
> }
>
> if(num == q->tail->num)
> {
> q->tail = q->tail->next;
Are you sure?
> }
>
> if(p)
> {
> p->next = h->next;
> }
> free(d);
> }
Your code seems messy here - how about this?
struct myStruct *previous = NULL;
struct myStruct *current;
for(current = q->head; current; current = current->next) {
if(num == current->num) {
if(current == q->head) {
q->head = q->head->next;
}
if(current == q->tail) {
q->tail = previous;
}
if(previous) {
previous->next = current->next;
}
free(current);
}
else {
previous = current;
}
}
[toc] | [prev] | [next] | [standalone]
| From | Johann Klammer <klammerj@NOSPAM.a1.net> |
|---|---|
| Date | 2012-05-08 20:50 +0200 |
| Message-ID | <4fa96af2$0$1586$91cee783@newsreader04.highway.telekom.at> |
| In reply to | #20494 |
arnuld wrote:
[SNIP]
> /* Added many months later */
> void removeAllMatches(struct myQueue* q, const int num)
> {
> if(NULL == q)
> {
> printf("Invalid Args\n");
> return;
> }
>
> if(NULL == q->head&& NULL == q->tail)
> {
> printf("Queue is already empty\n");
> }
> else if(NULL == q->head || NULL == q->tail)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> exit(EXIT_FAILURE);
> }
> else
> {
> struct myStruct *p, *d, *h;
> p = d = h = NULL;
> for(h = q->head; h; h = h->next)
> {
> d = h;
> if(num == d->num)
> {
> if(num == q->head->num )
> {
> q->head = q->head->next;
> }
>
> if(num == q->tail->num)
> {
> q->tail = q->tail->next;
> }
>
> if(p)
> {
> p->next = h->next;
> }
> free(d);
another
BUG:
you free() the memory pointed to by d (which is the same as h),
and in the for statement you access it: h = h->next
retrieve the next pointer _before_ you free() the element.
perhaps you should use some library for that...
glib or glibc's <search.h> perhaps...
> }
> else
> {
> p = h;
> }
> }
>
> }
> }
>
[SNIP]
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2012-05-11 00:39 -0700 |
| Message-ID | <20139213.396.1336721955573.JavaMail.geo-discussion-forums@pbbpp10> |
| In reply to | #20494 |
arnuld於 2012年5月8日星期二UTC+8下午4時09分39秒寫道:
> WANTED: Removing all elements matching a particular key from a Queue
> WHAT I GOT: Segfault
> WANTED: Segfaults in removeAllMatches(). I think routine/fucntion is too
> complex to be understood. removeAllMatches(arg1, arg2) is supposed to
> remove all elements from arg1 which match value of arg2.
>
>
>
>
> #include <stdio.h>
> #include <stdlib.h>
>
> struct myStruct
> {
> int num;
> struct myStruct* next;
> };
>
> struct myQueue
> {
> struct myStruct* head;
> struct myStruct* tail;
> };
>
>
> int enqueue(struct myQueue* q, int n);
> int dequeue(struct myQueue* q);
>
> struct myQueue* newQueue(void);
> void makeNull(struct myQueue* q);
> void removeAllMatches(struct myQueue* q, const int num);
>
> void printQueue(struct myQueue* q);
> void printStruct(struct myStruct* p);
>
>
>
> int main(void)
> {
> struct myQueue* q = newQueue();
> printQueue(q);
>
> enqueue(q, -1);
> enqueue(q, 100);
> enqueue(q, 38);
> enqueue(q, 100);
> enqueue(q, 38);
> enqueue(q, 9);
> enqueue(q, 100);
> printQueue(q);
>
> removeAllMatches(q, 100);
> printQueue(q);
> /* makeNull(q);
> printQueue(q); */
> free(q);
> q = NULL;
>
> return 0;
> }
>
>
>
> int enqueue(struct myQueue* q, int n)
> {
> int ret;
> if(NULL == q)
> {
> printf("Invalid Args\n");
> ret = -1;
> }
> else
> {
> struct myStruct* p = malloc(1 * sizeof *p);
> if(NULL == p)
> {
> printf("Out of memory\n");
> exit(EXIT_FAILURE);
> }
>
> p->num = n;
> p->next = NULL;
> if(NULL == q->tail && NULL == q->head)
> {
> printf("Empty Queue, Adding first element\n");
> q->head = q->tail = p;
> ret = 0;
> }
> else if(NULL == q->tail || NULL == q->head)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> free(p);
> ret = 1;
> }
> else
> {
> printf("Adding Element\n");
> q->tail->next = p;
> q->tail = p;
> ret = 0;
> }
> }
>
> return ret;
> }
>
>
>
> int dequeue(struct myQueue* q)
> {
> int ret = -1;
> if(NULL == q)
> {
> printf("Invalid Args\n");
> ret = -1;
> }
> else
> {
> struct myStruct* h;
> if(NULL == q->head && NULL == q->tail)
> {
> printf("Queue is already empty\n");
> ret = 0;
> }
> else if(NULL == q->head || NULL == q->tail)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> ret = 1;
> }
> else
> {
> h = q->head;
> q->head = q->head->next;
> free(h);
> if(NULL == q->head)
> {
> printf("Removing Last element left\n");
> q->head = q->tail = NULL;
> }
> else
> {
> printf("Removing Some element\n");
> }
> ret = 0;
> }
> }
>
> return ret;
> }
>
>
> /* Added many months later */
> void removeAllMatches(struct myQueue* q, const int num)
> {
> if(NULL == q)
> {
> printf("Invalid Args\n");
> return;
> }
>
> if(NULL == q->head && NULL == q->tail)
> {
> printf("Queue is already empty\n");
> }
> else if(NULL == q->head || NULL == q->tail)
> {
> printf("IN: %s @%d; ", __func__, __LINE__);
> printf("There is something seriously wrong with head/tail
> assignment of your Queue\n");
> exit(EXIT_FAILURE);
> }
> else
> {
> struct myStruct *p, *d, *h;
> p = d = h = NULL;
> for(h = q->head; h; h = h->next)
> {
> d = h;
> if(num == d->num)
> {
> if(num == q->head->num )
> {
> q->head = q->head->next;
> }
>
> if(num == q->tail->num)
> {
> q->tail = q->tail->next;
> }
>
> if(p)
> {
> p->next = h->next;
> }
> free(d);
> }
> else
> {
> p = h;
> }
> }
>
> }
> }
>
>
>
>
> void makeNull(struct myQueue* q)
> {
> if(q)
> {
> while(q->head) dequeue(q);
> }
> }
>
>
>
> struct myQueue* newQueue(void)
> {
> struct myQueue* p = malloc(1 * sizeof *p);
> if(NULL == p)
> {
> printf("Out of Memory\n");
> exit(EXIT_FAILURE);
> }
>
> return p;
> }
>
>
> void printQueue(struct myQueue* q)
> {
> if(q)
> {
> struct myStruct* p = q->head;
> for(; p; p = p->next) printStruct(p);
> printf("-----------------------------------------\n");
> }
> }
>
>
> void printStruct(struct myStruct* p)
> {
> if(p)
> {
> printf("title: %d\n", p->num);
> }
> }
>
> ======================== OUTPUT ==========================
> [arnuld@dune C]$ gcc -ansi -pedantic -Wall -Wextra Queue.c
> [arnuld@dune C]$ ./a.out
> -----------------------------------------
> Empty Queue, Adding first element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> Adding Element
> title: -1
> title: 100
> title: 38
> title: 100
> title: 38
> title: 9
> title: 100
> -----------------------------------------
> Segmentation fault
> [arnuld@dune C]$
>
>
>
>
>
> --
> arnuld
> http://LispMachine.Wordpress.com
I checked your code that I assume it requires not only the standard
operations of a queue.
I suggest you should use a link list.
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c
csiph-web