home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / c / 12978 < prev    next >
Encoding:
Text File  |  1992-08-30  |  4.4 KB  |  108 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!charon.amdahl.com!pacbell.com!att!linac!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!uunet.ca!wildcan!sq!msb
  3. From: msb@sq.sq.com (Mark Brader)
  4. Subject: Re: Copying file of int to 2-d array
  5. Message-ID: <1992Aug30.202246.27644@sq.sq.com>
  6. Organization: SoftQuad Inc., Toronto, Canada
  7. References: <chans.715161329@marsh> <3360@dozo.and.nl> <chans.715192721@marsh>
  8. Date: Sun, 30 Aug 92 20:22:46 GMT
  9. Lines: 97
  10.  
  11. > > >     array = (int *) malloc (98 * sizeof (int *));
  12. > >       array[counter] = (int *) malloc (98 * sizeof (int *));
  13.  
  14. Actually, the second "int *" should be "int".  This bug wouldn't make
  15. itself obvious unless you found a machine where int * uses fewer bytes
  16. than int.  This is one reason that I recommend using sizeof object
  17. rather than sizeof (type) in most cases; the line then becomes
  18.  
  19.           array[counter] = (int *) malloc (98 * sizeof *array[counter]);
  20.  
  21. The hardcoded constant 98 is of course also a bad idea.
  22.  
  23. > Sorry people, I did have the array[counter] in my program (it was a typo
  24. > error when I retyped my program for the post).
  25.  
  26. If you post code, post the actual code you're talking about; don't retype
  27. it.  If the example is too long to post, make a copy and edit away the
  28. irrelevant parts (note: declarations are never irrelevant).  Or better
  29. yet, construct a smaller program that has the same problem, verify that
  30. it has it, and post the smaller version!
  31.  
  32. (I violate my own rule below; the statements I post have not been tested.
  33. But these are isolated statements and not purportedly complete programs.)
  34.  
  35. > solved thanks to everyone.
  36.  
  37. So what was the real problem?
  38.  
  39.  
  40. > However, I have an alternative query, after using the dynamic array, is
  41. > it possible for me to free it with one command :-
  42. >    free (array)
  43. > or do I have to set a loop to free the array??
  44.  
  45. The rule is one call to free() for each call to malloc() or calloc().
  46. So if you allocate it in the way you did, you need a loop.  If the total
  47. size of the array is not too large, though, the loop can be avoided by
  48. doing a single malloc() for the whole array, except the dope vector
  49. which you malloc() first, and dealing off chunks of it for the dope
  50. vector to point to.  One of several equivalent ways to code this is:
  51.  
  52.       array = (int **) malloc (98 * sizeof *array);
  53.       array[0] = (int *) malloc (98 * 98 * sizeof *array[0]);
  54.       for (counter = 1; counter < 98; ++counter)
  55.          array[counter] = array[0] + 98*counter;
  56.  
  57. If the number of columns in the array is known at compile time, another
  58. option is to use a pointer-to-array type and eliminate the dope vector.
  59. Declare array as
  60.  
  61.       int (*array)[98];
  62. and write
  63.       array = (int (*)[98]) malloc (98 * sizeof *array);
  64.  
  65. and you are done.  The first two 98's are the number of columns, which
  66. must be a constant expression, while the third one is the number of
  67. rows -- see how hardcoded constants make the code hard to read?
  68.  
  69. However, both of these alternative solutions depend on the array size
  70. not being too large.  The largest value that you can depend on passing
  71. to malloc() on old implementations is 32767; values that won't fit in
  72. an int can never be passed.  Even if you can pass the value to malloc(),
  73. you may not be able to get a single chunk of memory that big, so these
  74. single-malloc() methods are more prone to failure.
  75.  
  76. Failure of malloc() being, incidentally, something that you should
  77. check for after every call to it.
  78.  
  79. >    for (counter = 0; counter < 98; ++counter)
  80. >        free (array[counter];
  81. >    free (array);
  82.  
  83. Modern implementations, based on ANSI C, do not require certain casts
  84. that were required in older implementations.  Your code uses one of these
  85. casts, but not another.  If portability to older implementations is not
  86. an issue, then the cast of the value returned from malloc() is needless;
  87. for example, you can write:
  88.  
  89.          array[counter] = malloc (98 * sizeof *array[counter]);
  90.  
  91. Whereas, if portability *is* an issue, or if you want to play safe about
  92. that, or if you simply think that redundant casts are good style, then a
  93. cast is equally needed on the value passed to free():
  94.  
  95.          free ((char *) array[counter]);
  96.  
  97. Modern and middle-aged implementations will also accept "void *" here
  98. in place of "char *".
  99.  
  100. -- 
  101. Mark Brader            "'You wanted it to WORK?  That costs EXTRA!'
  102. SoftQuad Inc., Toronto         is probably the second-place security hole
  103. utzoo!sq!msb, msb@sq.com     after simple carelessness."    -- John Woods
  104.  
  105. This article is in the public domain.
  106.