Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #74622 > unrolled thread
| Started by | "Morten W. Petersen" <morphex@gmail.com> |
|---|---|
| First post | 2015-11-02 10:17 +0100 |
| Last post | 2015-11-03 18:15 -0800 |
| Articles | 20 on this page of 49 — 12 participants |
Back to article view | Back to comp.lang.c
Memory and error management approaches "Morten W. Petersen" <morphex@gmail.com> - 2015-11-02 10:17 +0100
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-02 22:25 +1300
Re: Memory and error management approaches "Morten W. Petersen" <morphex@gmail.com> - 2015-11-02 10:36 +0100
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-02 22:41 +1300
Re: Memory and error management approaches "Morten W. Petersen" <morphex@gmail.com> - 2015-11-02 11:05 +0100
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-02 12:15 +0000
Re: Memory and error management approaches "Morten W. Petersen" <morphex@gmail.com> - 2015-11-02 20:31 +0100
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-03 09:48 +1300
Re: Memory and error management approaches supercat@casperkitty.com - 2015-11-02 13:17 -0800
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-03 10:29 +1300
Re: Memory and error management approaches supercat@casperkitty.com - 2015-11-02 13:48 -0800
Re: Memory and error management approaches "Morten W. Petersen" <morphex@gmail.com> - 2015-11-02 22:31 +0100
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-03 11:02 +1300
Re: Memory and error management approaches supercat@casperkitty.com - 2015-11-02 15:21 -0800
Re: Memory and error management approaches <william@wilbur.25thandClement.com> - 2015-11-03 17:24 -0800
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-04 14:38 +1300
Re: Memory and error management approaches <william@wilbur.25thandClement.com> - 2015-11-04 10:48 -0800
Re: Memory and error management approaches supercat@casperkitty.com - 2015-11-04 11:28 -0800
Re: Memory and error management approaches James Kuyper <jameskuyper@verizon.net> - 2015-11-04 14:54 -0500
Re: Memory and error management approaches Gareth Owen <gwowen@gmail.com> - 2015-11-06 07:50 +0000
Re: Memory and error management approaches <william@wilbur.25thandClement.com> - 2015-11-06 11:40 -0800
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-07 09:38 +1300
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-06 20:55 +0000
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-07 02:23 -0800
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-07 11:29 +0000
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-07 04:18 -0800
Re: Memory and error management approaches asetofsymbols@gmail.com - 2015-11-07 05:41 -0800
Re: Memory and error management approaches asetofsymbols@gmail.com - 2015-11-07 06:27 -0800
Re: Memory and error management approaches Sjouke Burry <burrynulnulfour@ppllaanneett.nnll> - 2015-11-07 18:20 +0100
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-07 10:28 -0800
Re: Memory and error management approaches gazelle@shell.xmission.com (Kenny McCormack) - 2015-11-07 19:01 +0000
Re: Memory and error management approaches raltbos@xs4all.nl (Richard Bos) - 2015-11-10 16:14 +0000
Re: Memory and error management approaches Gareth Owen <gwowen@gmail.com> - 2015-11-10 21:13 +0000
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-10 19:26 +0000
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-03 18:25 -0800
Re: Memory and error management approaches "Morten W. Petersen" <morphex@gmail.com> - 2015-11-06 10:05 +0100
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-02 02:15 -0800
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-02 12:01 +0000
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-02 06:05 -0800
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-02 17:18 +0000
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-02 09:27 -0800
Re: Memory and error management approaches Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-11-02 23:02 +0000
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-03 12:07 +1300
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-02 15:23 -0800
Re: Memory and error management approaches supercat@casperkitty.com - 2015-11-02 10:28 -0800
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-03 09:34 +1300
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-02 14:05 -0800
Re: Memory and error management approaches Ian Collins <ian-news@hotmail.com> - 2015-11-03 11:27 +1300
Re: Memory and error management approaches Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-03 18:15 -0800
Page 1 of 3 [1] 2 3 Next page →
| From | "Morten W. Petersen" <morphex@gmail.com> |
|---|---|
| Date | 2015-11-02 10:17 +0100 |
| Subject | Memory and error management approaches |
| Message-ID | <n179ne$64b$1@speranza.aioe.org> |
Hi there. So I'm working on my XML parser, and I'm thinking of ways to manage memory.. The design of the program will be one that uses loops rather than recursion, so exhausting the stack is unlikely. I was thinking of passing a parser object around, and on that parser object, link to a structure that contains references to all memory locations that need to be freed, all streams that need to be closed and so on, in the case of success or failure. And then have a function that goes through this error structure and deals with everything. This should work regardless the parsing succeeds or fails, and would also work with setjmp/longjmp. Any thoughts on this? A while ago someone wrote on comp.lang.c about writing a custom memory manager for performance; is that something that could be coupled with all of this? -Morten
[toc] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-02 22:25 +1300 |
| Message-ID | <d9ooh3F6ovuU4@mid.individual.net> |
| In reply to | #74622 |
Morten W. Petersen wrote: > Hi there. > > So I'm working on my XML parser, and I'm thinking of ways to manage > memory.. > > The design of the program will be one that uses loops rather than > recursion, so exhausting the stack is unlikely. > > I was thinking of passing a parser object around, and on that parser > object, link to a structure that contains references to all memory > locations that need to be freed, all streams that need to be closed > and so on, in the case of success or failure. Or just use C++.... > And then have a function that goes through this error structure and > deals with everything. > > This should work regardless the parsing succeeds or fails, and would > also work with setjmp/longjmp. You should forget about setjmp/longjmp and just handle errors locally. > Any thoughts on this? A while ago someone wrote on comp.lang.c about > writing a custom memory manager for performance; is that something that > could be coupled with all of this? Most of the platforms I'm familiar with provide specialised memory allocator libraries, you shouldn't have to roll yet another one for something as simple as XML parsing. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | "Morten W. Petersen" <morphex@gmail.com> |
|---|---|
| Date | 2015-11-02 10:36 +0100 |
| Message-ID | <n17app$82n$1@speranza.aioe.org> |
| In reply to | #74624 |
On 02.11.2015 10:25, Ian Collins wrote: [...] >> And then have a function that goes through this error structure and >> deals with everything. >> >> This should work regardless the parsing succeeds or fails, and would >> also work with setjmp/longjmp. > > You should forget about setjmp/longjmp and just handle errors locally. Why? >> Any thoughts on this? A while ago someone wrote on comp.lang.c about >> writing a custom memory manager for performance; is that something that >> could be coupled with all of this? > > Most of the platforms I'm familiar with provide specialised memory > allocator libraries, you shouldn't have to roll yet another one for > something as simple as XML parsing. Well it will also provide a (simple?) DOM and writer as well. So for example a search could be optimized by having certain things on one memory page etc. -Morten
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-02 22:41 +1300 |
| Message-ID | <d9opetF6ovuU6@mid.individual.net> |
| In reply to | #74626 |
Morten W. Petersen wrote: > On 02.11.2015 10:25, Ian Collins wrote: > [...] >>> And then have a function that goes through this error structure and >>> deals with everything. >>> >>> This should work regardless the parsing succeeds or fails, and would >>> also work with setjmp/longjmp. >> >> You should forget about setjmp/longjmp and just handle errors locally. > > Why? It will inevitably end in tears and/or much unnecessary complexity. >>> Any thoughts on this? A while ago someone wrote on comp.lang.c about >>> writing a custom memory manager for performance; is that something that >>> could be coupled with all of this? >> >> Most of the platforms I'm familiar with provide specialised memory >> allocator libraries, you shouldn't have to roll yet another one for >> something as simple as XML parsing. > > Well it will also provide a (simple?) DOM and writer as well. > > So for example a search could be optimized by having certain things > on one memory page etc. Trying to add such micro-optimisations on modern CPUs is seldom worth the effort. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | "Morten W. Petersen" <morphex@gmail.com> |
|---|---|
| Date | 2015-11-02 11:05 +0100 |
| Message-ID | <n17cgd$cf2$1@speranza.aioe.org> |
| In reply to | #74627 |
On 02.11.2015 10:41, Ian Collins wrote: > Morten W. Petersen wrote: >> On 02.11.2015 10:25, Ian Collins wrote: >> [...] >>>> And then have a function that goes through this error structure and >>>> deals with everything. >>>> >>>> This should work regardless the parsing succeeds or fails, and would >>>> also work with setjmp/longjmp. >>> >>> You should forget about setjmp/longjmp and just handle errors locally. >> >> Why? > > It will inevitably end in tears and/or much unnecessary complexity. Well, the error structure will contain pointers and be maybe 20 pointers big, and these pointers will in turn be linked lists if there is more than one entry.. If all dynamically allocated memory is freed and streams are closed on a longjmp, what's the problem? And by the way, is it proper practice to close streams when done with them, or should that be left to the caller? >>>> Any thoughts on this? A while ago someone wrote on comp.lang.c about >>>> writing a custom memory manager for performance; is that something that >>>> could be coupled with all of this? >>> >>> Most of the platforms I'm familiar with provide specialised memory >>> allocator libraries, you shouldn't have to roll yet another one for >>> something as simple as XML parsing. >> >> Well it will also provide a (simple?) DOM and writer as well. >> >> So for example a search could be optimized by having certain things >> on one memory page etc. > > Trying to add such micro-optimisations on modern CPUs is seldom worth > the effort. Well that would depend on the data type and size wouldn't it? -Morten
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2015-11-02 12:15 +0000 |
| Message-ID | <slrnn3eku6.5q5.grahn+nntp@frailea.sa.invalid> |
| In reply to | #74631 |
On Mon, 2015-11-02, Morten W. Petersen wrote: ... [His XML parser project] > And by the way, is it proper practice to close streams when done with > them, or should that be left to the caller? The one who opened the file should be the one to close it. But it would probably be nice if your core parser wasn't aware of I/O, but could be fed chunks of data: int parser_feed(Parser*, const char* data, size_t len); Then you could build variants which work on FILE*, or strings, or memory-mapped files ... on top of that. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | "Morten W. Petersen" <morphex@gmail.com> |
|---|---|
| Date | 2015-11-02 20:31 +0100 |
| Message-ID | <n18dmt$2uc$1@speranza.aioe.org> |
| In reply to | #74637 |
On 02.11.2015 13:15, Jorgen Grahn wrote: > On Mon, 2015-11-02, Morten W. Petersen wrote: > ... > [His XML parser project] > >> And by the way, is it proper practice to close streams when done with >> them, or should that be left to the caller? > > The one who opened the file should be the one to close it. > > But it would probably be nice if your core parser wasn't aware of I/O, > but could be fed chunks of data: > > int parser_feed(Parser*, const char* data, size_t len); > > Then you could build variants which work on FILE*, or strings, or > memory-mapped files ... on top of that. That's a good idea, enabling users to use it in that way, will be added. -Morten
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-03 09:48 +1300 |
| Message-ID | <d9q0hqF7v31U2@mid.individual.net> |
| In reply to | #74631 |
Morten W. Petersen wrote: > On 02.11.2015 10:41, Ian Collins wrote: >> Morten W. Petersen wrote: >>> On 02.11.2015 10:25, Ian Collins wrote: >>> [...] >>>>> And then have a function that goes through this error structure and >>>>> deals with everything. >>>>> >>>>> This should work regardless the parsing succeeds or fails, and would >>>>> also work with setjmp/longjmp. >>>> >>>> You should forget about setjmp/longjmp and just handle errors locally. >>> >>> Why? >> >> It will inevitably end in tears and/or much unnecessary complexity. > > Well, the error structure will contain pointers and be maybe 20 pointers > big, and these pointers will in turn be linked lists if there is more > than one entry.. > > If all dynamically allocated memory is freed and streams are closed on a > longjmp, what's the problem? You have introduced a laborious, manual and therefore error prone overhead to each resource allocation and release. There are good reasons why no attempt at bolting on an exception mechanism on to C has ever caught on. > And by the way, is it proper practice to close streams when done with > them, or should that be left to the caller? He who opens, closes. >>>>> Any thoughts on this? A while ago someone wrote on comp.lang.c about >>>>> writing a custom memory manager for performance; is that something that >>>>> could be coupled with all of this? >>>> >>>> Most of the platforms I'm familiar with provide specialised memory >>>> allocator libraries, you shouldn't have to roll yet another one for >>>> something as simple as XML parsing. >>> >>> Well it will also provide a (simple?) DOM and writer as well. >>> >>> So for example a search could be optimized by having certain things >>> on one memory page etc. >> >> Trying to add such micro-optimisations on modern CPUs is seldom worth >> the effort. > > Well that would depend on the data type and size wouldn't it? The time to look at custom allocation is after extensive testing and profiling shows a bottleneck with dynamic memory. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-11-02 13:17 -0800 |
| Message-ID | <cad90f0b-d6a2-4069-8c88-8283ea338ae5@googlegroups.com> |
| In reply to | #74698 |
On Monday, November 2, 2015 at 2:49:08 PM UTC-6, Ian Collins wrote: > There are good reasons why no attempt at bolting on an exception > mechanism on to C has ever caught on. It's all very nice and convenient to assume that things will always behave as expected, at least until the unexpected happens. Once one opens up that can of worms, there often is no really good approach--the best one can do is try to manage the least-evil approach. The scenario where I see a longjmp-based recovery as being appropriate would be one where inner-level code wouldn't be likely to be acquiring and releasing many resources that outer-level code didn't know about, so it wouldn't be necessary to use mid-level setjmp for most scenarios. > The time to look at custom allocation is after extensive testing and > profiling shows a bottleneck with dynamic memory. I've used custom allocators often in embedded systems where requirements could be met in such a way that fragmentation would never occur. On hosted systems, non-library code should generally use malloc/free, but that doesn't mean library code shouldn't allow clients to use some other forms of allocation that may be more appropriate to their needs.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-03 10:29 +1300 |
| Message-ID | <d9q2t5F7v31U4@mid.individual.net> |
| In reply to | #74702 |
supercat@casperkitty.com wrote: > On Monday, November 2, 2015 at 2:49:08 PM UTC-6, Ian Collins wrote: >> There are good reasons why no attempt at bolting on an exception >> mechanism on to C has ever caught on. > > It's all very nice and convenient to assume that things will always behave > as expected, at least until the unexpected happens. Once one opens up that > can of worms, there often is no really good approach--the best one can do > is try to manage the least-evil approach. The scenario where I see a > longjmp-based recovery as being appropriate would be one where inner-level > code wouldn't be likely to be acquiring and releasing many resources that > outer-level code didn't know about, so it wouldn't be necessary to use > mid-level setjmp for most scenarios. True enough but once added, longjmp based recovery makes the code vulnerable to any changes between the jump and landing site which do allocate a resource. In short it makes the code fragile. >> The time to look at custom allocation is after extensive testing and >> profiling shows a bottleneck with dynamic memory. > > I've used custom allocators often in embedded systems where requirements > could be met in such a way that fragmentation would never occur. On hosted > systems, non-library code should generally use malloc/free, but that doesn't > mean library code shouldn't allow clients to use some other forms of > allocation that may be more appropriate to their needs. You wouldn't really want a library to use a different allocation scheme to the rest of the application, especially if the scheme allocates its own working memory. In cases such as parsers, the library writer has no way of knowing which allocation scheme is appropriate for a particular use case. Consider the differing requirements of two use cases I mentioned earlier: small SOAP packets and large office documents. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-11-02 13:48 -0800 |
| Message-ID | <3c8abe2a-c26c-468f-9eff-2cc496a15794@googlegroups.com> |
| In reply to | #74703 |
On Monday, November 2, 2015 at 3:29:24 PM UTC-6, Ian Collins wrote: > True enough but once added, longjmp based recovery makes the code > vulnerable to any changes between the jump and landing site which do > allocate a resource. In short it makes the code fragile. Using longjmp without providing mid-level hooks may create problems for which no reasonable solution exists. In cases where manually returning up the call stack would be workable, that's often better, but in cases where the alternative to a longjmp would be a core dump, a longjmp can offer the possibility of handling things more gracefully. > You wouldn't really want a library to use a different allocation scheme > to the rest of the application, especially if the scheme allocates its > own working memory. In some cases it may be useful to malloc a chunk of memory and then sub- allocate chunks from that for temporary usage, especially if there is a frequent pattern of allocate temporary; allocate persistent; copy data from temporary to persistent (possibly reformatting it in the process); release temp. If all the temporary storage will be repeatedly allocated, released in LIFO order, re-allocated, etc. having a block of memory which is dedicated to that purpose can greatly reduce fragmentation elsewhere. > In cases such as parsers, the library writer has no way of knowing which > allocation scheme is appropriate for a particular use case. Consider > the differing requirements of two use cases I mentioned earlier: small > SOAP packets and large office documents. That's why I was suggesting the library should let the client decide. If the client has no problem with malloc/free, the library shouldn't either.
[toc] | [prev] | [next] | [standalone]
| From | "Morten W. Petersen" <morphex@gmail.com> |
|---|---|
| Date | 2015-11-02 22:31 +0100 |
| Message-ID | <n18kna$jnt$1@speranza.aioe.org> |
| In reply to | #74698 |
On 02.11.2015 21:48, Ian Collins wrote: > Morten W. Petersen wrote: [...] >> Well, the error structure will contain pointers and be maybe 20 pointers >> big, and these pointers will in turn be linked lists if there is more >> than one entry.. >> >> If all dynamically allocated memory is freed and streams are closed on a >> longjmp, what's the problem? > > You have introduced a laborious, manual and therefore error prone > overhead to each resource allocation and release. > > There are good reasons why no attempt at bolting on an exception > mechanism on to C has ever caught on. [...] >>> Trying to add such micro-optimisations on modern CPUs is seldom worth >>> the effort. >> >> Well that would depend on the data type and size wouldn't it? > > The time to look at custom allocation is after extensive testing and > profiling shows a bottleneck with dynamic memory. The reason I'm asking about custom allocation is that if I do some custom memory allocation, it isn't a big deal to also setup info that can be used on setjmp/longjmp tear-downs. A bit of what I've seen online is that memory allocators have speed benefits.. Also, seeing this: http://www.pjsip.org/pjlib/docs/html/group__PJ__POOL__GROUP.htm I can use a memory pool, and destroy it after a longjmp and memory has been handled. -Morten
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-03 11:02 +1300 |
| Message-ID | <d9q4r0F7v31U6@mid.individual.net> |
| In reply to | #74705 |
Morten W. Petersen wrote: > On 02.11.2015 21:48, Ian Collins wrote: >> >> The time to look at custom allocation is after extensive testing and >> profiling shows a bottleneck with dynamic memory. > > The reason I'm asking about custom allocation is that if I do some > custom memory allocation, it isn't a big deal to also setup info > that can be used on setjmp/longjmp tear-downs. > > A bit of what I've seen online is that memory allocators have speed > benefits.. Any coding technique can have speed benefits under specific conditions. I have used custom allocators, mainly in embedded applications, where the allocation patterns were known in advance and memory budgets were tight. I would only consider one on a hosted application if real world testing justified it. > Also, seeing this: > > http://www.pjsip.org/pjlib/docs/html/group__PJ__POOL__GROUP.htm > > I can use a memory pool, and destroy it after a longjmp and memory > has been handled.> I wouldn't bother until you can prove an advantage. Enabling longjump hackery isn't one in my book. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-11-02 15:21 -0800 |
| Message-ID | <71cb8c79-5ffe-4fbf-9ffa-60fb4ebcc4b2@googlegroups.com> |
| In reply to | #74708 |
On Monday, November 2, 2015 at 4:02:20 PM UTC-6, Ian Collins wrote: > I wouldn't bother until you can prove an advantage. Enabling longjump > hackery isn't one in my book. Unwinding failed object construction is generally problematic no matter what one does. If the input stream dies or one has sufficient advance warning of memory depletion, it may be possible to set an "object invalid" flag and jinx the input functions to pretend they see whatever kind of end tag they're expecting, let construction run its course, and then deconstruct the object in the usual manner. If, however, code finds itself without warning in the middle of constructing an object with no way to finish building something that can be given to the "deconstruct object" function, having a way to say "all the stuff I allocated using this context object is junk--get rid of it" can be much easier and more robust than scattering code throughout the object construction logic to handle failed constructor cleanup, whether one uses longjmp or a chain of "if (error) return;" logic.
[toc] | [prev] | [next] | [standalone]
| From | <william@wilbur.25thandClement.com> |
|---|---|
| Date | 2015-11-03 17:24 -0800 |
| Message-ID | <6b3ogc-uob.ln1@wilbur.25thandClement.com> |
| In reply to | #74705 |
Morten W. Petersen <morphex@gmail.com> wrote: > On 02.11.2015 21:48, Ian Collins wrote: >> Morten W. Petersen wrote: > [...] >>> Well, the error structure will contain pointers and be maybe 20 pointers >>> big, and these pointers will in turn be linked lists if there is more >>> than one entry.. >>> >>> If all dynamically allocated memory is freed and streams are closed on a >>> longjmp, what's the problem? >> >> You have introduced a laborious, manual and therefore error prone >> overhead to each resource allocation and release. >> >> There are good reasons why no attempt at bolting on an exception >> mechanism on to C has ever caught on. > [...] >>>> Trying to add such micro-optimisations on modern CPUs is seldom worth >>>> the effort. >>> >>> Well that would depend on the data type and size wouldn't it? >> >> The time to look at custom allocation is after extensive testing and >> profiling shows a bottleneck with dynamic memory. > > The reason I'm asking about custom allocation is that if I do some > custom memory allocation, it isn't a big deal to also setup info > that can be used on setjmp/longjmp tear-downs. > > A bit of what I've seen online is that memory allocators have speed > benefits.. IMO, the best reason to use a custom allocation scheme is to improve the quality of your code, not the performance. By improving the quality I mean improving readability, permitting simplifications, etc. But event that's a trade-off. See, e.g., OpenBSD's take on the OpenSSL Heartbleed fiasco, where they claim the biggest sin was that by using a custom allocator OpenSSL circumvented the sophisticated attack mitigations in OpenBSD's system allocator. > > Also, seeing this: > > http://www.pjsip.org/pjlib/docs/html/group__PJ__POOL__GROUP.htm A few criticisms: 1) The more sophisticated the allocator, the more complex it is. Ultimately you're just substituting one general purpose allocator for another. Modern system allocators already implement pools and other strategies. They're not all buddy allocators. 2) Debugging is usually much easier when dealing with the system allocator. For any debugging feature claimed by the library author, the capability and tooling for the system allocator will be even better, _especially_ on systems like Solaris, Linux, and OS X. (I can't speak for Window's CRT.) 3) Adding third-party dependencies, especially for mundane stuff like memory management, can become a maintanence headache, and possibly a source of frustration for users. 4) Custom allocators--for improving performance or code quality--are best when targeted at specific parts of your application. E.g. using a simple object stack/bump allocator for a parser, or a slab allocator for object construction. In these situations, the implementation is often trivial, and can provide benefits beyond what more general libraries offer. By looking at third-party libraries, you're already conceding that your approach is not focused on your immediate problems. > I can use a memory pool, and destroy it after a longjmp and memory > has been handled. Sure. I use that approach quite often. I've also used longjmp for error handling. But I only use these techniques in particular subcomponents, where the cost+benefit is maximized, and the implementation doesn't leak outside the interface. In terms of APIs, including internal APIs, you're almost always better off sticking to the system facilities, as you would most other languages. More importantly, sticking to tried-and-true patterns (e.g. RAII[1]) is far and away the most critical choice you can make. Obsessing over memory allocation is one of the favorite pastimes of C newbies (and, unfortunately, even some longtime C programmers), alongside dreaming of ways to abuse pointers and type punning. Certainly I went through that phase, and years later am still dealing with the costs. [1] RAII as a discipline works just as well in C as in C++. Despite lacking automatic destructors, the absolute benefit might be even greater in C because memory management can be more burdensome, or at least verbose.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-11-04 14:38 +1300 |
| Message-ID | <d9t5scFs0krU2@mid.individual.net> |
| In reply to | #74788 |
william@wilbur.25thandClement.com wrote: > > [1] RAII as a discipline works just as well in C as in C++. Despite lacking > automatic destructors, the absolute benefit might be even greater in C > because memory management can be more burdensome, or at least verbose. Could you expand on that statement? -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | <william@wilbur.25thandClement.com> |
|---|---|
| Date | 2015-11-04 10:48 -0800 |
| Message-ID | <fg0qgc-mgq.ln1@wilbur.25thandClement.com> |
| In reply to | #74789 |
Ian Collins <ian-news@hotmail.com> wrote: > william@wilbur.25thandClement.com wrote: >> >> [1] RAII as a discipline works just as well in C as in C++. Despite lacking >> automatic destructors, the absolute benefit might be even greater in C >> because memory management can be more burdensome, or at least verbose. > > Could you expand on that statement? > RAII was formalized as a method for ensuring object state consistency--or rather minimizing the times and places that state is inconsistent--in order to mitigate problems with exceptions. Because if an exception occurs when an object is in an inconsistent state, you have problems. If you fix the problems by sprinkling conditionals all over your code to handle the additional number of states, you have even more problems. Resource acquisition is initialization means, in negative terms, no _lazy_ initializations. That is, you shouldn't allocate an object and then lazily allocate submembers. For example, you shouldn't allocate a FILE pointer and lazily open the underlying file description. Because now that FILE object has twice as many possible states. Worse, it not only has more states, but in many cases you've multiplied the number of failure scenarios. Now an ENOENT, for example, could happen on any operation, not just at fopen time. (FILE is a poor example here because there are other possible errors when reading or writing, but with many of types of objects errors can only happen at construction time.) To my mind, RAII is all about condensing resource acquisition into as few places as possible. Another principle that follows from RAII is maintaining single ownership. A corollary, you mentioned elsethread, is he who allocates, deallocates. But fundamentally it's about striving to maintain a tidy hierarchy of object ownership at all times, even during construction. Among other things, this allows many failure paths to merge up the stack via the tree of constructors, so it can dramatically simplify error handling. If you follow the discipline, manging object lifetime becomes simpler. Object destruction becomes easier for the implementation because there are fewer conditionals to worry about in the destructor. Destruction is easier for the caller because there should be fewer interdependent relationships. Likewise, when aborting a failed initialization, the error path is simplified because unwinding a partially initialized object is made easier as destruction of any initialied submembers is simpler. So even though C lacks automatic destructors, RAII can still dramatically simplify destruction. I realize that RAII has a much more technical meaning, especially in the context of C++. In C++ the discipline means applying several C++ specific idioms, such as smart pointers (or similar constructs) for heap-allocated objects so that lifetime is bound to the stack. But arguably that's just syntactic sugar. You can implement OOP patterns in C, including virtual methods, you just don't have the benefit of compiler constructs. Likewise, for RAII you just need to manually ensure that all objects are ultimately bound to a single stack reference, so destruction of the tree of resources is as simple as calling a single destructor. (Or if they're not, that you're employing some sort of reference counting, so even though ownership is shared, the details can be hidden behind a single destructor so the contract from the caller's perspective is the same.) Most of the burden of managing object lifetime comes from the complexity of interdependencies and failure modes; by following an RAII discipline you minimze both of those. Ultimately one might simply consider this good code hygiene. But it helps if there's a label you can use as a reference to the general methology, and I think it's fair to appropriate RAII as that label. The compiler constructs employed in C++ have analogous manual idioms in C.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-11-04 11:28 -0800 |
| Message-ID | <cc5e279a-ab81-4252-bab2-219c1b5e129a@googlegroups.com> |
| In reply to | #74862 |
On Wednesday, November 4, 2015 at 1:00:21 PM UTC-6, wil...@wilbur.25thandclement.com wrote: > Resource acquisition is initialization means, in negative terms, no _lazy_ > initializations. That is, you shouldn't allocate an object and then lazily > allocate submembers. For example, you shouldn't allocate a FILE pointer and > lazily open the underlying file description. Because now that FILE object > has twice as many possible states. I don't think RAII precludes lazy initialization, but it requires that it be encapsulated via an object that has an *explicit* "awaiting initialization" state, *and whose destructor can be safely called even when the object is in that state*. If an object lazily acquires a resource, it would be entirely possible (and not particularly unexpected) that until the object has actually needed the resource, nothing in the universe would care if it disappeared without its destructor having been called first. What's essential, though, is that even if calling the destructor before the resource is acquired has no useful effect, it's still *safe*. Thus, code which owns the resource wrapper does not have to concern itself with whether any resource has actually been acquired; it can (and should) call the destructor in any case.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-11-04 14:54 -0500 |
| Message-ID | <n1dnm8$k1u$1@dont-email.me> |
| In reply to | #74862 |
On 11/04/2015 01:48 PM, william@wilbur.25thandClement.com wrote: > Ian Collins <ian-news@hotmail.com> wrote: >> william@wilbur.25thandClement.com wrote: >>> >>> [1] RAII as a discipline works just as well in C as in C++. Despite lacking >>> automatic destructors, the absolute benefit might be even greater in C >>> because memory management can be more burdensome, or at least verbose. >> >> Could you expand on that statement? ... > I realize that RAII has a much more technical meaning, especially in the > context of C++. In C++ the discipline means applying several C++ specific > idioms, such as smart pointers (or similar constructs) for heap-allocated > objects so that lifetime is bound to the stack. But arguably that's just > syntactic sugar. I will argue that point - it is not "just" syntactic sugar - it's extremely valuable syntactic sugar which renders inaccurate your claim that it "works just as well in C as in C++". That syntactic sugar makes it work a whole lot better in C++ than in C. -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Gareth Owen <gwowen@gmail.com> |
|---|---|
| Date | 2015-11-06 07:50 +0000 |
| Message-ID | <8737wjk1lw.fsf@gmail.com> |
| In reply to | #74869 |
James Kuyper <jameskuyper@verizon.net> writes:
> I will argue that point - it is not "just" syntactic sugar - it's
> extremely valuable syntactic sugar which renders inaccurate your claim
> that it "works just as well in C as in C++". That syntactic sugar makes
> it work a whole lot better in C++ than in C.
I completely agree. The key to RAII is not that Resource Acquistion Is
Initialization but its converse -- End-of-Life Is *Automatic* Resource
Release.
You can fake the former easily in C ("no lazy initialisation") - the
converse is much much harder. To release resources in C but you *have*
to do it all by hand (or use a GC, if the only resource you're
interested in is memory), which is absolutely not "works just as well in
C" unless you have unlimited programmers, unlimited patience or
unlimited time.
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web