need some expert to 'vette' my code
Author |
Message |
IceLav #1 / 13
|
 need some expert to 'vette' my code
I'm new to programming C in linux environment & need some expert advice on whether I've handled pointers for record structures from a file correctly. my prog juz wanna read out structures stored in a file, and I need to use the low level read/write functions. I have a record counter in the main menu which i pass in here as a pointer since I'll be doing the counting here. this will result in segmentation fault, though. the last time I ran a trace it broke at the line (if *reccount == 0) head = new; i dunno why this is so. can anybody tell? /* * readfile - reads file descriptor specified by caller * param * int fd - file descriptor * int *reccount - pointer to main menu's record counter * return struct shares * - pointer to the head of list */ struct shares *readfile(int fd, int *reccount) { ssize_t readsize; /* mem size read from file */ struct shares *head = NULL, *current; struct shares *new = (struct shares *)malloc(sizeof(struct shares)); /* set counter to 0 since only reads at startup */ *reccount = 0; /* while some data being read */ while ((readsize = read(fd, new, sizeof(struct shares))) > 0) { if (readsize != sizeof(struct shares)) printf("read size different : %d/%d bytes \n", readsize, sizeof(struct shares)); /* initialise the fresh record's next pointer to NULL */ new->next = NULL; if (*reccount == 0) head = new; else current->next = new; current = new; *reccount ++; new = (struct shares *)malloc(sizeof(struct shares)); } /* if !EOF then error */ if (readsize < 0) printf("errno = %d\n", errno); /* report */ printf("read size : %d/%d bytes\n", readsize, sizeof(struct shares)); printf("%d records read.\n", *reccount); return head; /* address of 1st record struct */ Quote: }
thanx! Aaron --
|
Wed, 06 Feb 2002 03:00:00 GMT |
|
 |
Kalle Olavi Niemital #2 / 13
|
 need some expert to 'vette' my code
Quote:
> *reccount ++;
Change that to: (*reccount)++; But I don't know if this was what caused the segfault, since I didn't get one. The function also leaks the last structure it allocates. --
|
Thu, 07 Feb 2002 03:00:00 GMT |
|
 |
Homer Simpso #3 / 13
|
 need some expert to 'vette' my code
IceLava a crit dans le message ... Quote: >I'm new to programming C in linux environment & need some expert advice >on whether I've handled pointers for record structures from a file >correctly. my prog juz wanna read out structures stored in a file, and >I need to use the low level read/write functions. >I have a record counter in the main menu which i pass in here as a >pointer since I'll be doing the counting here. this will result in >segmentation fault, though. the last time I ran a trace it broke at the >line >(if *reccount == 0) > head = new; >i dunno why this is so. can anybody tell?
Well, your code uses non standard functions and definitions(struct shares, ssize_t etc...), it is not easy to test your code on a standard compiler ! I suppose that you call the function like this : int iReccount; p= readfile(fd, &iReccount); May be you have made a cuttent error that is to use a non initialised pointer like this : int *piReccount; p= readfile(fd, piReccount); This could explain the execution error. Some remarks concerning your coding : Quote: > struct shares *new = (struct shares *)malloc(sizeof(struct shares));
- "new" is a reserved key word in C++. You'd better avoid to use it ! - It is a good idea to use calloc() instead of malloc(). The data will be initialized to 0. struct shares *pNew = (struct shares *)calloc(sizeof(struct shares),1); Quote: > /* set counter to 0 since only reads at startup */ > *reccount = 0;
to avoid bad surprises, it is better to check the pointer before use : assert(reccount!=NULL); see your documentation about assert() : Highly recommended to write reliable code ! Quote: > /* while some data being read */ > while ((readsize = read(fd, new, sizeof(struct shares))) > 0) > { > if (readsize != sizeof(struct shares)) > printf("read size different : %d/%d bytes \n", readsize, >sizeof(struct shares));
This generally means that you are reading the end of the file. It is not an error. Quote: > /* initialise the fresh record's next pointer to NULL */ > new->next = NULL;
So "new" is a chain list ! first new ! Quote: > if (*reccount == 0)
If "reccount" points to a valid memory zone, no prolem ! Quote: > *reccount ++;
I prefer (*reccount)++; -- HS --
|
Thu, 07 Feb 2002 03:00:00 GMT |
|
 |
Chris Tore #4 / 13
|
 need some expert to 'vette' my code
Quote:
>Well, your code uses non standard functions and definitions(struct shares, >ssize_t etc...), it is not easy to test your code on a standard compiler !
Indeed. Quote: >> struct shares *new = (struct shares *)malloc(sizeof(struct shares)); >- "new" is a reserved key word in C++. You'd better avoid to use it !
Eh? He is writing C, not C++; why should he care what is reserved in C++? "var" is a keyword in Pascal, so perhaps we should avoid that too? :-) Quote: >- It is a good idea to use calloc() instead of malloc(). The data will be >initialized to 0.
Calloc() produces all-bits-zero, which is not always appropriate. I almost never use calloc() myself. If you have some data structure that needs to be set to mostly-zero or all-zero, and it might contain objects of floating-point or pointer type, you can do something like this instead: static struct S zero_S; struct S *p = malloc(sizeof *p); /* no cast here; C is not C++ */ ... make sure p != NULL ... *p = zero_S; Since zero_S is static, all its members are implicitly set to an appropriate kind of zero, whatever bit pattern that may be, so this sets *p to all-zero-values, which may or may not be all-zero-bits. -- In-Real-Life: Chris Torek, Berkeley Software Design Inc
--
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Robert O'Dow #5 / 13
|
 need some expert to 'vette' my code
Quote: [Snip] Quote: > >> struct shares *new = (struct shares *)malloc(sizeof(struct shares)); > >- "new" is a reserved key word in C++. You'd better avoid to use it ! > Eh? He is writing C, not C++; why should he care what is reserved > in C++? "var" is a keyword in Pascal, so perhaps we should avoid that > too? :-)
A significant number of compilers, used to compile C code, are really C++ compilers. Some of those will {*filter*}on this sort of code, while others will have compiler options to turn off C++ compilation. Also keep in mind that one option for reusing C code is within a C++ program. In some instances, that means recompiling it as C++. Quote: > >- It is a good idea to use calloc() instead of malloc(). The data will be > >initialized to 0. > Calloc() produces all-bits-zero, which is not always appropriate. > I almost never use calloc() myself. [Snip ...]
Same here. Your milage will vary, obviously, but I've found that use of calloc is often slower than use of malloc (presumably because of the initialisation). Generally, I prefer to use malloc and then initialise explicitly. Since I rarely have to initialise a complete new data structure to zero (there is usually one or more fields that will be initialised to non-zero), I normally only use malloc. In short, use of calloc or malloc is a trade-off. In my code, the trade-offs favour malloc. -<Automagically included trailer> Robert O'Dowd Ph +61 (8) 8259 6546 MOD/DSTO Fax +61 (8) 8259 5139 P.O. Box 1500 Email:
Salisbury, South Australia, 5108 Disclaimer: Opinions above are mine and may be worth what you paid for them --
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Peter Seeba #6 / 13
|
 need some expert to 'vette' my code
Quote: >Calloc() produces all-bits-zero, which is not always appropriate. >I almost never use calloc() myself.
(A side note: I suspect Chris Torek has not written any code in the last five years which will ever be executed on a machine on which all-bits-zero doesn't work for pointers and floating point types. This turns out to be a part of the reason people in alt.folklore.computers cited "the ability to find old posts by Chris Torek" to be a major advantage of a long-term Usenet archive.) Quote: >If you have some data structure >that needs to be set to mostly-zero or all-zero, and it might >contain objects of floating-point or pointer type, you can do >something like this instead: > static struct S zero_S; > struct S *p = malloc(sizeof *p); /* no cast here; C is not C++ */ > ... make sure p != NULL ... > *p = zero_S; >Since zero_S is static, all its members are implicitly set to an >appropriate kind of zero, whatever bit pattern that may be, so this >sets *p to all-zero-values, which may or may not be all-zero-bits.
I'm sure some of the newbies want to know *why* this works and the other doesn't. Here's the idea. There Exist (that's C guru for "I've never seen or touched, but I have been told about theoretical designs for") machines on which the floating point value 0.0, or the null pointer, is not actually stored with all the bits in memory zeroed. There are many and varied reasons for this; in practice, You Don't Need To Know. The problem is this: If you say static int p, *q; the compiler, at compile-time, gets to look at this and say "p is an int, I'll write a 0 there. oooh, q is a pointer, better put the special magic null value there". If you say void *v = calloc(sizeof(struct foo), 10); there's no way for 'calloc' to know what it needs to do. You can create a situation where even with all the information the compiler starts with, you can trick the system into creating a block of memory with "the wrong type of zero". So, it doesn't try. It just writes all-bits-zero and hopes. This means you lose, if you're on a weird system. So, we end up with stuff like what Chris shows above. In C9X, you can get one step simpler: *p = (struct S) { 0 }; This magically does the right thing, without the explicit creation of a static object. (In fact, the chances are that, on a reasonable compiler, this will end up creating just about exactly the same code that the other one did.) -s --
C/Unix wizard, Pro-commerce radical, Spam fighter. Boycott Spamazon! Will work for interesting hardware. http://www.plethora.net/~seebs/ Visit my new ISP <URL:http://www.plethora.net/> --- More Net, Less Spam! --
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Adam Sprag #7 / 13
|
 need some expert to 'vette' my code
Quote:
> > Eh? He is writing C, not C++; why should he care what is reserved > > in C++? "var" is a keyword in Pascal, so perhaps we should avoid that > > too? :-) > A significant number of compilers, used to compile C code, are really > C++ compilers. Some of those will {*filter*}on this sort of code, while > others will have compiler options to turn off C++ compilation.
tsk. A compiler that compiles both C and C++ (and other language) code should be able to tell what language you're using (on some platforms) from the source code file extension, and set itself accordingly. <disclaimer> (Note : _On_some_platforms_. I know that the standard has nothing to say about the form that source code is supplied in, even to the extent of not neccessarily specifying that a file system need exist.) </disclaimer> Quote: > Also keep in mind that one option for reusing C code is within a C++ > program. In some instances, that means recompiling it as C++.
Agreed. I'm not saying that avoiding C++ identifiers is not a good idea. It is. It should just not be _neccessary_. Adam -- Apparently [...] police in many lands are now complaining that local arrestees are insisting on having their Miranda rights read to them, just like perps in American TV cop shows. When it's explained to them that they are in a different country, where those rights do not exist, they become outraged. Starsky and Hutch reruns, dubbed into diverse languages, may turn out, in the long run, to be a greater force for human rights than the [United States] Declaration of Independence. -- Neal Stephenson (Cryptonomicon - http://www.*-*-*.com/ ~mccoy/beginning_print.html) ---------------- The opinions expressed in this email are mine alone, and do not neccesarily represent those of my employer, my parents, or the people who wrote the email software I use. --
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Francis Glassboro #8 / 13
|
 need some expert to 'vette' my code
Quote: >Eh? He is writing C, not C++; why should he care what is reserved >in C++? "var" is a keyword in Pascal, so perhaps we should avoid that >too? :-)
Well there is a serious difference, C code can generally be compiled by a C++ compiler (and often is). It would be a rare piece of C source that compiled with a Pascal compiler. Francis Glassborow Journal Editor, Association of C & C++ Users 64 Southfield Rd Oxford OX4 1PA +44(0)1865 246490 All opinions are mine and do not represent those of any organisation --
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Jerry Coff #9 / 13
|
 need some expert to 'vette' my code
says... [ ... ] Quote: > Here's the idea. There Exist (that's C guru for "I've never seen or touched, > but I have been told about theoretical designs for") machines on which the > floating point value 0.0, or the null pointer, is not actually stored with > all the bits in memory zeroed. There are many and varied reasons for this; > in practice, You Don't Need To Know.
If memory about what machines you've used serves me correctly, you HAVE seen, touched and in fact regularly use machines that don't necessarily use all-bits-zero to represent 0.0. In fact, machines that require all bits to be zero to represent 0.0 are probably in the minority at the present time -- the typical Intel, PowerPC, SPARC, etc., do NOT require this. In fairness, I should point out that I believe on all of them, all bits being set to 0 will give a value of 0.0 when treated as floating point, but most will treat a number of other bit-patterns as values of 0.0 as well. If memory serves, the ancient CDC mainframes were what I'd consider a bit smarter about things: they treated a pattern all 0 bits as roughly equivalent to what IEEE floating point would call a signalling NaN. This meant that most of the time if you tried to use an un-initialized floating point variable, the program would immediately tell you so. OTOH, it's barely possible that the pattern was not all zeroes, but the compiler initialized unused memory to the right pattern; it's been long enough that I don't remember for sure. --
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Peter Seeba #10 / 13
|
 need some expert to 'vette' my code
Quote:
>says... >> Here's the idea. There Exist (that's C guru for "I've never seen or touched, >> but I have been told about theoretical designs for") machines on which the >> floating point value 0.0, or the null pointer, is not actually stored with >> all the bits in memory zeroed. There are many and varied reasons for this; >> in practice, You Don't Need To Know. >In fairness, I should point out that I >believe on all of them, all bits being set to 0 will give a value of >0.0 when treated as floating point, but most will treat a number of >other bit-patterns as values of 0.0 as well.
Yeah. I've never actually seen all-bits-zero not work. Of course, it's probably been five or ten years since I experimented at all; I don't really care. See, I have source, and I've read how calloc really works. ... type_t t = precognitive_rtti(v); if (!strncmp(t, "pointer to", 10) || strstr(t, "float")) { FILE *fp = fopen("/dev/boss", "w+"); fprintf(fp, "it is imperative that all of our software be tested on a CDC mainframe.\n"); fclose(fp); } They just wait for you to get careless, then pounce. -s --
C/Unix wizard, Pro-commerce radical, Spam fighter. Boycott Spamazon! Will work for interesting hardware. http://www.plethora.net/~seebs/ Visit my new ISP <URL:http://www.plethora.net/> --- More Net, Less Spam! --
|
Fri, 08 Feb 2002 03:00:00 GMT |
|
 |
Jerry Coff #11 / 13
|
 need some expert to 'vette' my code
says... Quote:
> >A good point. If I had a ba{*filter*}t (a LARGE ba{*filter*}t) I'd keep one > >down there to test things on. Unfortunately, the supply of vestal > >{*filter*}s isn't what it once was, so I'm afraid keeping one running > >would be awfully hard nowadays anyway...and rebooting takes a trained > >team around a half hour at best! > I'd settle for a sufficiently good "arbitrary implementation simulator".
I know the idea's come up before, but I have to admit it'd be kind of fun, wouldn't it? Quote: > >Ah, so there's finally somebody else who realizes what computers > >really are: malevolent creatures from another dimension, sent here to > >punish us for our good deeds. (It must be punishment for good deeds-- > >I'm the nicest person I've ever met, and they cause me problems ALL
> Maybe you should run Unix. <grin, duck, and run>
Oh, but I do run UNIX, which is the major problem. NT is a decided contrast since it mostly runs itself. Unfortunately, there's another contrast: NT doesn't run well on a SPARC. This is a decided contrast to Solaris, which doesn't run well on...anything. --
|
Sat, 09 Feb 2002 03:00:00 GMT |
|
 |
Gene Wirchen #12 / 13
|
 need some expert to 'vette' my code
Quote:
>>A good point. If I had a ba{*filter*}t (a LARGE ba{*filter*}t) I'd keep one >>down there to test things on. Unfortunately, the supply of vestal >>{*filter*}s isn't what it once was, so I'm afraid keeping one running >>would be awfully hard nowadays anyway...and rebooting takes a trained >>team around a half hour at best! >I'd settle for a sufficiently good "arbitrary implementation simulator".
Bring on the nasal demons! [snip] Sincerely, Gene Wirchenko Computerese Irregular Verb Conjugation: I have preferences. You have biases. He/She has prejudices. --
|
Sun, 10 Feb 2002 03:00:00 GMT |
|
 |
Anton Treuenfel #13 / 13
|
 need some expert to 'vette' my code
Quote:
> Here's the idea. There Exist (that's C guru for "I've never seen or touched, > but I have been told about theoretical designs for") machines on which the > floating point value 0.0, or the null pointer, is not actually stored with > all the bits in memory zeroed. There are many and varied reasons for this; > in practice, You Don't Need To Know.
In fact, There Is (that's my guess as to what a C guru might use for "I've seen and/or touched a real machine on which...") an old machine still in occasional use, the Commodore 64, whose built-in ROM BASIC interpreter manipulated five-byte (40-bit) floating point values (one exponent byte, four manitissa bytes). For reasons You Don't Need To Know, if the exponent byte was zero, the floating point value as a whole was considered to be zero, regardless of any values in any of the mantissa bytes. And this relates to C because the ROM floating point routines were sufficiently orthogonal (to use a word that's been floating about here lately) to the remainder of the BASIC interpreter that they could be called by other, completely independent programs running on the C64. Which is how at least one C compiler for the C64 handled the problem of providing floating point support. - Anton --
|
Sun, 10 Feb 2002 03:00:00 GMT |
|
|
|