jdm5548@diamond.tamu.edu (James Darrell McCauley) (09/07/90)
Could someone lend a hand? Topic is FAQ #19, allocating memory
for an array. The problem is that 'lint' doesn't like what I'm
doing.
Here's some source:
#include<stdio.h>
#include<malloc.h>
main()
{
int i, nrows=10, ncolumns=10;
double **array;
array = (double **)malloc(nrows * ncolumns * sizeof(double *));
for(i = 0; i < nrows; i++)
array[i] = (double *)malloc(ncolumns * sizeof(double));
}
/*
Code from answer to #19 in FAQ list (dated Aug 3 by 'ls -l'):
int **array = (int **)malloc(nrows * ncolumns * sizeof(int *));
for(i = 0; i < nrows; i++)
array[i] = (int *)malloc(ncolumns * sizeof(int));
*/
/* output from lint:
test.c(8): warning: possible pointer alignment problem
test.c(10): warning: possible pointer alignment problem
malloc, arg. 1 used inconsistently llib-lc(383) :: test.c(8)
malloc, arg. 1 used inconsistently llib-lc(383) :: test.c(10)
*/
Why am I getting these warnings? I get them using lint that
(I assume) is bundled with the OS. SunOS Release 4.0.3c on a Sparc.
If I run them on my Sun 3/60 with SunOS Release 4.0.3, I don't
get the warnings. ('diff "4.0.3" "4.0.3c"' ?) Do I have a broken
lint on the Sparc?
Should the argument to malloc be cast (unsigned) (and FAQ list changed)?
If I make this change, lint doesn't scream about arguments being used
incorrectly.
Darrell McCauley
cpcahil@virtech.uucp (Conor P. Cahill) (09/08/90)
In article <8056@helios.TAMU.EDU> jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: > int i, nrows=10, ncolumns=10; > double **array; > > array = (double **)malloc(nrows * ncolumns * sizeof(double *)); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ While this has nothing to do with your lint problems, I think this should be: array = (double **)malloc(nrows * sizeof(double *)); > for(i = 0; i < nrows; i++) > array[i] = (double *)malloc(ncolumns * sizeof(double)); >} >/* >/* output from lint: >test.c(8): warning: possible pointer alignment problem >test.c(10): warning: possible pointer alignment problem This you will always get from lint. The problem is that malloc is defined as returning a pointer to char which has looser alignment requirements than pointer to pointer. Since malloc guarrantees that the result is suitably alligned for all data types, you can ignore this message. >malloc, arg. 1 used inconsistently llib-lc(383) :: test.c(8) >malloc, arg. 1 used inconsistently llib-lc(383) :: test.c(10) This is caused by the argument to malloc being unsigned, not signed. A cast in your code will fix this. -- Conor P. Cahill (703)430-9247 Virtual Technologies, Inc., uunet!virtech!cpcahil 46030 Manekin Plaza, Suite 160 Sterling, VA 22170
chris@mimsy.umd.edu (Chris Torek) (09/09/90)
In article <1990Sep08.022034.8444@virtech.uucp> cpcahil@virtech.uucp (Conor P. Cahill) writes: [re the lint error from `ptr = malloc(expr * sizeof(sometype))': malloc, arg. 1 used inconsistently] >This is caused by the argument to malloc being unsigned, not signed. A >cast in your code will fix this. Note that the cast is only required in old, broken compilers where the result of `sizeof' is an int instead of a size_t (typically unsigned int). These compilers are remarkably widespread (and, unfortunately, fixing them breaks some existing code, which is why I have not fixed ours here yet). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
hp@vmars.tuwien.ac.at (Peter Holzer) (09/10/90)
cpcahil@virtech.uucp (Conor P. Cahill) writes: >In article <8056@helios.TAMU.EDU> jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: > array = (double **)malloc(nrows * sizeof(double *)); >> for(i = 0; i < nrows; i++) >> array[i] = (double *)malloc(ncolumns * sizeof(double)); >>malloc, arg. 1 used inconsistently llib-lc(383) :: test.c(8) >>malloc, arg. 1 used inconsistently llib-lc(383) :: test.c(10) >This is caused by the argument to malloc being unsigned, not signed. A >cast in your code will fix this. No! Don't fix your code, which is correct. Fix the lint library. The argument to malloc should be the type returned by sizeof (): size_t (an unsigned integral type). -- | _ | Peter J. Holzer | Think of it | | |_|_) | Technische Universitaet Wien | as evolution | | | | | hp@vmars.tuwien.ac.at | in action! | | __/ | ...!uunet!mcsun!tuvie!vmars!hp | Tony Rand |
cpcahil@virtech.uucp (Conor P. Cahill) (09/11/90)
In article <1803@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes: >cpcahil@virtech.uucp (Conor P. Cahill) writes: > >>This is caused by the argument to malloc being unsigned, not signed. A >>cast in your code will fix this. > >No! Don't fix your code, which is correct. Fix the lint library. >The argument to malloc should be the type returned by sizeof (): size_t >(an unsigned integral type). The argument to malloc is defined in the library (i.e. where malloc() is encoded). running lint against the source builds the lint library and therefore the lint library will correctly reflect what the code has (besides, without code, you can rebuild a lint library). The problem that the original poster ran into is that on his system the type of sizeof() is an integer. However, the type of malloc's argument is an unsigned integer. -- Conor P. Cahill (703)430-9247 Virtual Technologies, Inc., uunet!virtech!cpcahil 46030 Manekin Plaza, Suite 160 Sterling, VA 22170
hp@vmars.tuwien.ac.at (Peter Holzer) (09/11/90)
cpcahil@virtech.uucp (Conor P. Cahill) writes: >In article <1803@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes: >>cpcahil@virtech.uucp (Conor P. Cahill) writes: >> >>>This is caused by the argument to malloc being unsigned, not signed. A >>>cast in your code will fix this. >> >>No! Don't fix your code, which is correct. Fix the lint library. >>The argument to malloc should be the type returned by sizeof (): size_t >>(an unsigned integral type). >The argument to malloc is defined in the library (i.e. where malloc() >is encoded). running lint against the source builds the lint library and >therefore the lint library will correctly reflect what the code has (besides, >without code, you can rebuild a lint library). The lint libraries are ASCII files on our system. Are they in a compiled form on yours ? >The problem that the original poster ran into is that on his system >the type of sizeof() is an integer. However, the type of malloc's >argument is an unsigned integer. We have the same problem on our machines (DECstations, Ultrix 2.1, cc 1.31), but I use gcc, so I didn't run across it before: In <sys/types.h>: typedef int size_t; /* returned by sizeof */ /* this is a compiler bug. should be unsigned */ In /usr/lib/lint/llib-lc: char * malloc(n) unsigned n; {static char c; return(&c);} Exactly the situation described. Now if I want to shut up lint about foop = malloc (sizeof (struct foo)); what should I cast the argument to malloc to? * Unsigned is not a good choice. On the next system I want to port my program to, malloc might be declared char * malloc (unsigned long n); and if int and long are different sizes I might not get what I want. * Unsigned long is even worse. It might not even work on the machine I use now. * Size_t is the type I have already. * Any other ideas ? So what I propose is the following: Check if the non-negative values of int have the same representation as the corresponding values of unsigned ints (This is true for all machines I know, and is guarantueed for ANSI C). If this holds, it does not matter if you are passing a non-negative int or an unsigned to a function expecting unsigned. Because of this you can change the above line in llib-lc to: char * malloc(n) int n; {static char c; return(&c);} I know this is a hack, but it is a hack that does not force you to write non-portable programs, as the cast-workaround does. (The other possibility is not to use lint, which I am forced to do, because lint gags on my prototypes, but in general, I would not recommend that). -- | _ | Peter J. Holzer | Think of it | | |_|_) | Technische Universitaet Wien | as evolution | | | | | hp@vmars.tuwien.ac.at | in action! | | __/ | ...!uunet!mcsun!tuvie!vmars!hp | Tony Rand |
karl@haddock.ima.isc.com (Karl Heuer) (09/12/90)
In article <1806@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes: >cpcahil@virtech.uucp (Conor P. Cahill) writes: >>>No! Don't fix your code, which is correct. Fix the lint library... >>The argument to malloc is defined in the library (i.e. where malloc() >>is encoded). running lint against the source builds the lint library and >>therefore the lint library will correctly reflect what the code has (besides, >>without code, you can rebuild a lint library). > >The lint libraries are ASCII files on our system. Are they in a compiled >form on yours ? Common practice on modern machines is to supply a compiled form (llib-lc.ln) as well as the ASCII form (llib-lc). You probably have both, and just never noticed. >[The problem is that sizeof() incorrectly returns a signed int, and size_t is >defined that way in <sys/types.h>, but malloc() expects an unsigned int.] >Now if I want to shut up lint about [malloc(sizeof(x))], what should I cast >the argument to malloc to? Don't cast it at all! The idea is to make the code *correct*, not to get rid of spurious warnings caused by a known compiler/lint bug. >[You could change the lint library to declare the argument to be int] This would create a new warning for correct code (malloc(n*sizeof(T)), where n is an unsigned variable). Better to fix the compiler, if possible. >(The other possibility is not to use lint, which I am forced to do, because >lint gags on my prototypes, but in general, I would not recommend that). Lint is commonly implemented as a shell script. Find the place where it does something like "cpp | lint1", and insert a filter that converts ANSI-isms to forms that are acceptable to K&R-based lint. (I currently use a sed script to change "void *" to "char *", and a deprotoizer that's tuned to my personal coding style.) Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
chris@mimsy.umd.edu (Chris Torek) (09/12/90)
In article <1806@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes: [part of an aside:] >The lint libraries are ASCII files on our system. Are they in a compiled >form on yours ? Yes; they are built from ASCII files which are also installed. The situation differs under some versions of System V. >In <sys/types.h>: > typedef int size_t; /* returned by sizeof */ > /* this is a compiler bug. > should be unsigned */ The `size_t' you find in <sys/types.h> is *NOT* the `size_t' meant by ANSI C. <sys/types.h>'s `size_t' is the `size of a text, data, or stack segment in clicks', not the `size of a contiguous memory block in bytes'. They merely (unfortunately) happen to have the same name. In 4.3BSD-reno, the `size_t' in <sys/types.h> has been renamed `segsz_t' and a proper (unsigned) size_t is defined in the proper ANSI <std*.h> files. One can fix this on binary-only Unix systems by changing that one line in <sys/types.h> to read typedef int segsz_t; #ifdef KERNEL #define size_t segsz_t #endif Unfortunately, you have to remember to reinstall this change with every system upgrade until your vendor catches on. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
hp@vmars.tuwien.ac.at (Peter Holzer) (09/12/90)
karl@haddock.ima.isc.com (Karl Heuer) writes: >In article <1806@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes: >>The lint libraries are ASCII files on our system. Are they in a compiled >>form on yours ? >Common practice on modern machines is to supply a compiled form (llib-lc.ln) >as well as the ASCII form (llib-lc). You probably have both, and just never >noticed. Yes. Now that you told me, I found them. >>cpcahil@virtech.uucp (Conor P. Cahill) writes: >>>In article <1803@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes: >>>>cpcahil@virtech.uucp (Conor P. Cahill) writes: >>>>>This is caused by the argument to malloc being unsigned, not signed. A >>>>>cast in your code will fix this. >>>>No! Don't fix your code, which is correct. >>[The problem is that sizeof() incorrectly returns a signed int, and size_t is >>defined that way in <sys/types.h>, but malloc() expects an unsigned int.] >>Now if I want to shut up lint about [malloc(sizeof(x))], what should I cast >>the argument to malloc to? >> [Various types and why they don't work deleted] >Don't cast it at all! The idea is to make the code *correct*, not to get rid >of spurious warnings caused by a known compiler/lint bug. Just what I said. >>[You could change the lint library to declare the argument to be int] >This would create a new warning for correct code (malloc(n*sizeof(T)), where n >is an unsigned variable). Better to fix the compiler, if possible. Ok, I hereby withdraw my proposal. New proposal: Complain to your compiler/lint vendor and wait for a new release. >>(The other possibility is not to use lint, which I am forced to do, because >>lint gags on my prototypes, but in general, I would not recommend that). >Lint is commonly implemented as a shell script. Find the place where it does >something like "cpp | lint1", and insert a filter that converts ANSI-isms to >forms that are acceptable to K&R-based lint. (I currently use a sed script to >change "void *" to "char *", and a deprotoizer that's tuned to my personal >coding style.) I will try it. My deprotoizer is a little less strict about white space than yours (but twice the size), but it doesn't handle pointers to functions either, so there will be some programs where it won't work. If it does work in most cases I'll be happy, though. The best solution would be a GNU lint, which does understand ANSI C and GNU extensions (e.g. volatile void exit (int);). PS: I like "Heuer's Law". If I hadn't seen it in some other guy's signature already, I would have put it into mine. -- | _ | Peter J. Holzer | Think of it | | |_|_) | Technische Universitaet Wien | as evolution | | | | | hp@vmars.tuwien.ac.at | in action! | | __/ | ...!uunet!mcsun!tuvie!vmars!hp | Tony Rand |
dricejb@drilex.UUCP (Craig Jackson drilex1) (09/14/90)
A poster recently wondered why a statement like double *ptr = (double *) malloc(ncols * sizeof(double)); gave lint complaints about the argument to malloc(). People here have been blathering on about broken compilers, erroneous lint libraries, etc, thinking that 'sizeof()' is returning an int on that machine. Wouldn't a more reasonable explanation be that 'ncols' is an int, and that particular compiler treats 'int * unsigned' as 'int' (or 'long int')? I don't have all of the rules about value-preserving vs unsignedness-preserving burned into my head, but such an explanation sure makes sense to me... -- Craig Jackson dricejb@drilex.dri.mgh.com {bbn,axiom,redsox,atexnet,ka3ovk}!drilex!{dricej,dricejb}
karl@haddock.ima.isc.com (Karl Heuer) (09/15/90)
In article <15495@drilex.UUCP> dricejb@drilex.UUCP (Craig Jackson drilex1) writes: >People here have been blathering on about broken compilers, erroneous lint >libraries, etc, thinking that 'sizeof()' is returning an int on that machine. > >Wouldn't a more reasonable explanation be that 'ncols' is an int, and that >particular compiler treats 'int * unsigned' as 'int' (or 'long int')? There is a well-known implementation where sizeof() returns a signed int. (Understandable, since K&R 1 didn't say.) I've never heard of one that thinks int*uint is signed. (Which would be harder to defend, since both Classic and ANSI C agree that it isn't.) Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint