jdm5548@diamond.tamu.edu (James Darrell McCauley) (09/09/90)
How do you professionals deal with insignificant(?) ravings from lint (or other high quality C program verifiers) such as the following: >test.c(x): warning: possible pointer alignment problem which was caused by the malloc in: >double **dmatrix(nr,nc) >int nr,nc; >{ > double **m = NULL; > > m = (double **) malloc( (unsigned) nr * sizeof(double *) ); > if (!m) ... From what netlanders tell me, this warning is explanined as: (by Conor P. Cahill) |> 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. Well, I can just ignore warnings like this, but those who review my code (professors, employers, clients) are not likely to. It makes an bad impression and frankly, I find it a little embarrassing. (I'm embarrassed for those who publish code in which lint detects things like unused arguments, etc). I could just: #ifndef lint m = (double *) malloc(... #endif but before long, the code looks disgusting. Do you just ignore warnings like this and remain confident in your code, or do you do your best to work around them? By the way, I got this error while using a Sparc under Sun OS 4.0.3c, but not under 4.0.3 (which perplexes me). --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - James Darrell McCauley jdm5548@diamond.tamu.edu Dept of Ag. Engineering (409) 845-6484 Texas A&M University, College Station, Texas 77843-2117, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mcdonald@aries.scs.uiuc.edu (Doug McDonald) (09/09/90)
In article <8086@helios.TAMU.EDU> jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: >How do you professionals deal with insignificant(?) ravings from >lint (or other high quality C program verifiers) such as the >following: > >>test.c(x): warning: possible pointer alignment problem >which was caused by the malloc in: > >>double **dmatrix(nr,nc) >>int nr,nc; >>{ >> double **m = NULL; >> >> m = (double **) malloc( (unsigned) nr * sizeof(double *) ); >> if (!m) ... > >From what netlanders tell me, this warning is explanined as: >(by Conor P. Cahill) >|> 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. > >Well, I can just ignore warnings like this, but those who review >my code (professors, employers, clients) are not likely to. It makes >an bad impression and frankly, I find it a little embarrassing. It is NOT embarrassing to you. It just plain a BUG in lint. Pure and simple. Complain to the person that sold you the broken "lint". A checker program really OUGHT to understand the rules of what it is checking. One of those rules concersn alignments of the return value of malloc. Doug McDonald
chris@mimsy.umd.edu (Chris Torek) (09/09/90)
In article <8086@helios.TAMU.EDU> jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: >How do you professionals deal with insignificant(?) ravings from >lint (or other high quality C program verifiers) such as [the bogus `possible pointer alignment problem' messages from malloc]? >... I can just ignore warnings like this, but those who review >my code (professors, employers, clients) are not likely to. Since the warning is due to a bug in lint, those who do not ignore it are simply compounding the problem. The real cure is to fix lint. >By the way, I got this error while using a Sparc under Sun OS 4.0.3c, >but not under 4.0.3 (which perplexes me). Looks like someone fixed it, but had to back out the fix (or else 4.0.3 and 4.0.3c were separate development efforts, which is entirely possible). This happens to be easy to fix as a special case inside lint (add an `/*ALIGNOK*/' lint-pragma that can be used in <stdXXX.h> files to tag the special functions malloc and calloc). A harder one is varargs routines: /* used as error(quit, errno, fmt, ...) */ /* VARARGS3 */ error(va_alist) /* note Classic C <varargs.h>, not New C <stdarg.h> */ va_dcl { int quit, e; char *fmt; va_list ap; va_start(ap); quit = va_arg(ap, int); e = va_arg(ap, int); fmt = va_arg(ap, int); ... One would like lint to verify that the first three arguments are indeed <int> <int> and <char *> respectively. (Indeed, since this particular function behaves like printf, one would also like lint to verify subsequent arguments the way the 4.3BSD-reno lint [thanks to Arthur Olson] verifies arguments to printf, fprintf, and sprintf.) The only solution I have to this is: #ifdef lint /* VARARGS3 */ error(quit, e, fmt) int quit, e; char *fmt; { } #define error lint_error #endif ... definition of error() as before ... #undef error You must then ignore all `function lint_.* defined but not used' errors. If you were to use #ifdef lint /* VARARGS3 */ error(quit, e, fmt) int quit, e; char *fmt; { } #else ... definition of error() ... #endif then lint would not be able to check the code inside error() itself. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
duane@anasaz.UUCP (Duane Morse) (09/09/90)
Here are two suggestions to remove lint's pointer alignment complaint. 1) Put #ifdef lint/#endif around the code and do something innocuous when running lint. If the profs read the code carefully, this may raise their eyebrows. 2) Write your own "malloc" subroutine which returns 0 for success and a nonzero value for failure; pass a pointer to where you want to store the address and have the routine interpret it as a char **; use a variable of the type you really need (struct whatever *) and cast it to (char **) in the subroutine call -- lint won't complain about any of this. By the way, if the prof's really complain about this lint 'error' in your program, it doesn't say much about their knowledge of lint. -- Duane Morse e-mail: duane@anasaz (or ... asuvax!anasaz!duane) (602) 861-7609
guy@auspex.auspex.com (Guy Harris) (09/10/90)
>How do you professionals deal with insignificant(?) ravings from >lint (or other high quality C program verifiers) such as the >following: With "egrep". >By the way, I got this error while using a Sparc under Sun OS 4.0.3c, >but not under 4.0.3 (which perplexes me). I suspect you meant "but not on a Sun-[23] under 4.0.3", not "but not under 4.0.3". The key is the SPARC, not the "c"; the SunOS (BSD-environment) "lint" is little pickier about alignment complaints when run on a SPARC machine - it does them even if you don't give "lint" the "-h" option. (Of course, I always use "-h" anyway, so I don't notice the difference....)
karl@haddock.ima.isc.com (Karl Heuer) (09/10/90)
In article <8086@helios.TAMU.EDU> jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: >How do you professionals deal with insignificant(?) ravings from lint [like] >test.c(x): warning: possible pointer alignment problem This is caused by a long-standing bug in lint. It could have been fixed long ago, but this hasn't been a high-priority item with AT&T. (It's "fixed" in SVR4 by going full swing in the other direction; ANSI-lint now fails to report some genuine alignment problems, as I understand the situation.) And it's almost invariably a bad idea to muck up your code with a workaround: >#ifndef lint > m = (double *) malloc(... >#endif Not only does this look ugly (and in my opinion, creates a *worse* impression than the presence of a well-known spurious lint warning), but it can easily lead to further problems. For example, lint will now believe that "m" is uninitialized. But if you must have a workaround, one fairly clean one is to use a separate interface for each type: #if !defined(lint) #define mkdouble() ((double *)malloc(sizeof(double))) #define rmdouble(p) free((void *)p) #else extern double *mkdouble(void); extern void rmdouble(double *); #endif which might be a good idea anyway since it leaves room for more complex constructors/destructors in a future revision. Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
volpe@underdog.crd.ge.com (Christopher R Volpe) (09/10/90)
In article <8086@helios.TAMU.EDU>, jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: |>How do you professionals deal with insignificant(?) ravings from |>lint (or other high quality C program verifiers) such as the |>following: |> |>>test.c(x): warning: possible pointer alignment problem I don't know if this will work, since my lint doesn't complain about this possible alignment problem, but how about trying the following? #include <malloc.h> #ifdef LINT double *(*_malloc)() = (double *(*)()) malloc; /* note underscore */ #define malloc (*_malloc) #endif This declares "_malloc" to be a pointer to a function returning pointer to double, and initializes it with the address of the malloc routine, suitably cast. Then, all calls to "malloc" actually use "(*_malloc)", which returns objects with proper alignment as far as lint is concerned. ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (09/11/90)
Here's a nifty little gizmo that implements /*NOSTRICT*/ by postprocessing lint's output for you. #!/usr/bin/perl 'di'; 'ig00'; # # $Header: nostrict,v 1.1 90/08/11 13:26:31 lwall Locked $ # # $Log: nostrict,v $ # Revision 1.1 90/08/11 13:26:31 lwall # Initial revision # for $arg (@ARGV) { next unless $arg =~ /\.[ch]$/; open(IN,$arg); while (<IN>) { vec($ok{$arg}, $., 1) = 1 if m#/\*\s*NOSTRICT\s*\*/# .. m#;\s*($|/\*)#; } close IN; } open(LINT, "-|") || exec @ARGV; while (<LINT>) { next unless ($file,$line) = /(\S+)\((\d+\))/; next unless defined $ok{$file}; $_ = '' if vec($ok{$file}, $line, 1); next unless ($file,$line) = /::\s*(\S+)\((\d+\))/; next unless defined $ok{$file}; $_ = '' if vec($ok{$file}, $line, 1); } continue { print; } ############################################################################## # These next few lines are legal in both Perl and nroff. .00; # finish .ig 'di \" finish diversion--previous line must be blank .nr nl 0-1 \" fake up transition to first page again .nr % 0 \" start at page 1 '; __END__ ############# From here on it's a standard manual page ############ .TH NOSTRICT 1 "August 11, 1990" .AT 3 .SH NAME nostrict \- postprocesses lint output to implement NOSTRICT directives .SH SYNOPSIS .B nostrict lint [lint_args] .SH DESCRIPTION .I Nostrict runs the command supplied in the rest of the arguments on the command line, and then weeds out any lint complaints referring to statements preceded by the /*NOSTRICT*/ directive that the lint documentation documents but that lint doesn't implement. .SH ENVIRONMENT No environment variables are used. .SH FILES None. .SH AUTHOR Larry Wall .SH "SEE ALSO" lint(1) .SH DIAGNOSTICS None. Relies on lint to tell you about missing files. .SH BUGS Should probably differentiate the errors you want NOSTRICT for from the errors you don't. Larry Wall lwall@jpl-devvax.jpl.nasa.gov
rsalz@bbn.com (Rich Salz) (09/12/90)
In <8086@helios.TAMU.EDU> jdm5548@diamond.tamu.edu (James Darrell McCauley) writes: [ Summary: extern char *malloc(); double **dpp = (double **)malloc((unsigned int)n * sizeof (double*)); causes lint to complain "possible pointer alignment problem". ] Some people said ignore it, but James replied: >Well, I can just ignore warnings like this, but those who review >my code (professors, employers, clients) are not likely to. Then, simply put, they are not competent to review your code. If you need a better solution, you can often fool lint by writing your own malloc function that returns something with worst-case alignment. For example: #define NEW(type, count) xmalloc(count * sizeof (type)) typedef double *ALIGN; ALIGN xmalloc(i) int i; { ALIGN p = (ALIGN)malloc((unsigned int)i); if (p == NULL) FatalError("no memory"); return p; } double **dpp = NEW(double*, n); -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.
dave@imax.com (Dave Martindale) (09/14/90)
In article <2985@anasaz.UUCP> duane@anasaz.UUCP (Duane Morse) writes: >Here are two suggestions to remove lint's pointer alignment complaint. > >2) Write your own "malloc" subroutine which returns 0 for success and >a nonzero value for failure; pass a pointer to where you want to store >the address and have the routine interpret it as a char **; use a >variable of the type you really need (struct whatever *) and cast it >to (char **) in the subroutine call -- lint won't complain about any >of this. This is a BAD idea. If you are on a machine where a byte and (short, int, long, float, double) pointers do not have the same representation, this won't work. When you declare the "extra" allocator argument as a char **, and then store the memory address via it, the memory allocator will always store the address in char * format - it doesn't know what actual type of pointer you want to use. In contrast, even though lint complains, when you use malloc in the normal way, the C compiler knows that malloc is returning a char * and you want a different type of pointer, and will generate code to do the conversion if any is needed on this machine. So, your suggestion gets rid of the lint complaint, but gives code that is no longer portable. If I were marking such an assignment, I'd mark that as an error.