From torenvliet at ispnet.ca Fri Jul 4 18:01:36 2003 From: torenvliet at ispnet.ca (Nick Torenvliet) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Problems getting started Message-ID: <1057356096.8185.6.camel@aquila> Hi I am trying to use splint on a project that links to glib and libxml. I am getting parse errors in glib.h, which prevent splint from continuing its check into my code. As a first step I used +skip-sys-headers to disable the glib.h error but now I have an error on the first reference to a type in libxml. How can I disable/fix the glib error, without incurring the libxml error? Nick Torenvliet From vhamberg at centerfieldtechnology.com Fri Jul 11 10:46:12 2003 From: vhamberg at centerfieldtechnology.com (Vern Hamberg) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error Message-ID: <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> I am new to splint and am running it against an IBM iSeries (AS/400) and get the following message on one of its standard includes: i:\qibm\include\unistd.h(185,62): Invalid character in #if: \ Line in error and the continuation are #if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) Apparently the iSeries allows continuations in #if constructs and splint thinks this is not OK. This is part of the support for Unix-style functions on this non-Unix platform. It does have what is called the Integrated File System, which has a Unix-equivalent file system in it. These continuation characters are common in the headers, since they are restricted, in the main, to 80-character lines (the source is actually in fixed length database files of special characteristics). Any suggestions? TIA Vern From torenvliet at ispnet.ca Fri Jul 11 11:44:05 2003 From: torenvliet at ispnet.ca (Nick Torenvliet) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error In-Reply-To: <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> References: <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> Message-ID: <1057938245.5002.72.camel@aquila> Vern, I've been on the list for a week now, and this is the first post I've seen.... I am not sure where everyone is On Fri, 2003-07-11 at 10:46, Vern Hamberg wrote: > I am new to splint and am running it against an IBM iSeries (AS/400) and > get the following message on one of its standard includes: > > i:\qibm\include\unistd.h(185,62): Invalid character in #if: \ > > Line in error and the continuation are > > #if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ > || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) > > Apparently the iSeries allows continuations in #if constructs and splint > thinks this is not OK. > > This is part of the support for Unix-style functions on this non-Unix > platform. It does have what is called the Integrated File System, which has > a Unix-equivalent file system in it. > > These continuation characters are common in the headers, since they are > restricted, in the main, to 80-character lines (the source is actually in > fixed length database files of special characteristics). > > Any suggestions? > > TIA > > Vern > > > _______________________________________________ > splint-discuss mailing list > splint-discuss@cs.virginia.edu > http://www.splint.org/mailman/listinfo/splint-discuss > From roland.illig at gmx.de Sat Jul 12 07:01:38 2003 From: roland.illig at gmx.de (Roland Illig) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error In-Reply-To: <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> References: <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> Message-ID: <20030712110138.GB4026@burse.uni-hamburg.de> On Fri, Jul 11, 2003 at 09:46:12AM -0500, Vern Hamberg wrote: > I am new to splint and am running it against an IBM iSeries (AS/400) and > get the following message on one of its standard includes: > > i:\qibm\include\unistd.h(185,62): Invalid character in #if: \ > > Line in error and the continuation are > > #if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ > || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) > > Apparently the iSeries allows continuations in #if constructs and splint > thinks this is not OK. Well, I created a test file containing these lines: #if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) #error foo #else #error bar #endif and let splint check it -- without complaints. Splint uses the GCC preprocessing library, which should also accept this code without complaining about it. So it could be another reason for this error message. What character set is the AS/400 using? Some kind of ASCII? Roland From Simon.Hosie at connexionz.co.nz Sun Jul 13 18:21:07 2003 From: Simon.Hosie at connexionz.co.nz (Simon Hosie) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error Message-ID: Roland Illig: > Well, I created a test file containing these lines: ... > What character set is the AS/400 using? Some kind of ASCII? What's the expected behaviour with a trailing space, or DOS newlines? From ok at cs.otago.ac.nz Sun Jul 13 18:42:20 2003 From: ok at cs.otago.ac.nz (Richard A. O'Keefe) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error Message-ID: <200307132242.h6DMgK5o148337@atlas.otago.ac.nz> Vern Hamberg asked about i:\qibm\include\unistd.h(185,62): Invalid character in #if: \ Line in error and the continuation are #if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) Apparently the iSeries allows continuations in #if constructs and splint thinks this is not OK. No, that's not the problem. These continuation characters are common in the headers, since they are restricted, in the main, to 80-character lines (the source is actually in fixed length database files of special characteristics). The problem is an extremely common one for C systems using fixed length records. You see, that line really looks like "#if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))" "\\" " " "\n" The records are 80 columns wide. The backslash is in column 61. That means that there are 19 spaces after it. But according to the C standard, \ is a line continuation character *ONLY* when it is *IMMEDIATELY* followed by newline. The only really reliable way to handle line continuations in a system with fixed length records is to ensure that the backslash is always in the very last column. Basically, the question is, "if you start with fixed length records, where should the newline go?" On one view, the one Splint is using, you get _all_ the characters in the record, followed by a newline. On another view, trailing blanks are ignored. It appears that this other view is the one your compiler is using. Read the documentation for fopen() on your system very carefully. There may be some kind of option (other there may be a related function with such an option) to "trim" input records. If you can find such an option, modify the Splint sources to use it, then Splint will "see" the same characters as your compiler. This problem can also come up in UNIX and Windows systems, if you accidentally type a space after the backslash. In most editors it is hard to see blanks at the ends of lines. The C89 committee *should* have dealt with this by defining the line continuation sequence to be backslash, white space*, newline. Another alternative would be to modify the Splint tokeniser to do this, but I'd expect it to be easier to modify calls to fopen(). From peter at trusteddebian.org Mon Jul 14 01:45:15 2003 From: peter at trusteddebian.org (Peter Busser) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error In-Reply-To: <200307132242.h6DMgK5o148337@atlas.otago.ac.nz> References: <200307132242.h6DMgK5o148337@atlas.otago.ac.nz> Message-ID: <20030714054515.GB18258@trusteddebian.org> Hi! > This problem can also come up in UNIX and Windows systems, if you > accidentally type a space after the backslash. In most editors it > is hard to see blanks at the ends of lines. In vi you can do the following (in command mode): :se list This will display TAB as ^I and \n as $. You can turn it off by: :se nolist > The C89 committee > *should* have dealt with this by defining the line continuation > sequence to be backslash, white space*, newline. In that case it would be different from the way the bakslash is used as a continuation character in e.g. the shell or make. Groetjes, Peter Busser -- The Adamantix Project Taking trustworthy software out of the labs, and into the real world http://www.adamantix.org/ From mne at mosaic-ag.com Mon Jul 14 02:18:18 2003 From: mne at mosaic-ag.com (Miroslaw Dobrzanski-Neumann) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error In-Reply-To: <20030714054515.GB18258@trusteddebian.org> References: <200307132242.h6DMgK5o148337@atlas.otago.ac.nz> <20030714054515.GB18258@trusteddebian.org> Message-ID: <20030714061818.GA19863@mailsrv.mosaic-ag.com> On Mon, Jul 14, 2003 at 07:45:15AM +0200, Peter Busser wrote: > Hi! > > > This problem can also come up in UNIX and Windows systems, if you > > accidentally type a space after the backslash. In most editors it > > is hard to see blanks at the ends of lines. > > In vi you can do the following (in command mode): > > :se list > > This will display TAB as ^I and \n as $. You can turn it off by: > > :se nolist If you are uisng vim you can colour badly used sequences of blanks in .vimrc: let c_space_errors = 1 syntax on This catches: - blanks (spaces or tabs) before end of line - spaces followed by tabs (not in literals) Regards Miros?aw -- Miros?aw Dobrza?ski-Neumann E-mail: mne@mosaic-ag.com This message uses utf-8 encoding From vhamberg at centerfieldtechnology.com Mon Jul 14 12:57:58 2003 From: vhamberg at centerfieldtechnology.com (Vern Hamberg) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error In-Reply-To: <20030712110138.GB4026@burse.uni-hamburg.de> References: <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030711093519.025d5be8@mail.centerfieldtechnology.com> Message-ID: <5.1.0.14.2.20030714111501.00b9f4b8@mail.centerfieldtechnology.com> Roland, et al. AS/400 is an EBCDIC machine. However, it can be translated to ASCII via the Windows networking (samba) client (called NetServer on the 400 and herein). So, splint sees the source as ASCII. Someone else (Simon?) mentioned trailing spaces and DOS newlines - the fixed-length record has no newlines. The file is actually a special kind of database table, 3 columns - sequence number, change date (of the row), and source data. Special handling strips all but the source data when it is opened in, say, TextPad using NetServer. But the trailing blanks are all there in TextPad and would be there for splint to see as well. A newline would probably be inserted by translation after the length of the data column (80 characters in this case). Richard asks about fopen(). AS/400 has 2 kinds of files - those in this IFS (Integrated File System) are stream fiels, as we are used to in DOS and Unix, and Data Management (RDBMS) files (fixed length, although somewhat complicated by variable length columns now). fopen, although a best fit for the stream files, can be used on the record types. But these files are not normally handled by the system using fopen - the system uses its native format, and I believe trailing spaces are ignored, and without a continuation marker, trailing blanks will be treated as a single blank, just as newlines are in DOS-like systems, right? Hope any of that makes sense - the 400 was designed primarily as a business, financial calculation machine with a very nice DB optimized for all that. C was not too much a part of its original design - languages like COBOL and RPG are more native. Support for C and Java, etc., are there now and actually pretty strong, esp. Java, but there's a lot of work to merge the free-form "C" context with fixed-length records. I might be stuck, as the files in question are provided by IBM and I cannot change them. I CAN copy them and use those, but, boy, there are a lot of them. The low-level OS of the 400 now, BTW, is written in C++ - the source is usually entered on an AIX server, then they have a cross-compiler (IBM's internal one) that generates the executables. Thanks for all your replies - it's been illuminating. OOH, I just learned about options on the compile commands, to checkout the source for problems, like conditional statements with assignments. Have to try this. Might be a built-in lint! Thanks again. Vern At 01:01 PM 7/12/2003 +0200, you wrote: >On Fri, Jul 11, 2003 at 09:46:12AM -0500, Vern Hamberg wrote: > > I am new to splint and am running it against an IBM iSeries (AS/400) and > > get the following message on one of its standard includes: > > > > i:\qibm\include\unistd.h(185,62): Invalid character in #if: \ > > > > Line in error and the continuation are > > > > #if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ > > || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) > > > > Apparently the iSeries allows continuations in #if constructs and splint > > thinks this is not OK. > >Well, I created a test file containing these lines: > >#if ((!(defined _POSIX_SOURCE) && !(defined _POSIX1_SOURCE))\ > || ((defined _POSIX1_SOURCE) && (_POSIX1_SOURCE != 1))) >#error foo >#else >#error bar >#endif > >and let splint check it -- without complaints. Splint uses the GCC >preprocessing library, which should also accept this code without >complaining about it. So it could be another reason for this error >message. > >What character set is the AS/400 using? Some kind of ASCII? > >Roland From ok at cs.otago.ac.nz Mon Jul 14 18:47:58 2003 From: ok at cs.otago.ac.nz (Richard A. O'Keefe) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error Message-ID: <200307142247.h6EMlwAV190780@atlas.otago.ac.nz> I wrote: > The C89 committee > *should* have dealt with this by defining the line continuation > sequence to be backslash, white space*, newline. Peter Busser wrote: In that case it would be different from the way the bakslash is used as a continuation character in e.g. the shell or make. So what? The shell and make should *also* be fixed, but that was a job for the POSIX.2 committee, not the C89 committee. The point is that some mainframe C compilers *do* treat backslash space* newline sensibly, and that the committee should, in the interests of portability, have blessed the practice. There are no C programs which can be broken by this. From hooman.foroughi at hp.com Mon Jul 14 19:00:34 2003 From: hooman.foroughi at hp.com (Foroughi, Hooman) Date: Wed Mar 22 17:10:10 2006 Subject: [splint-discuss] Invalid character error Message-ID: <67FCA4DC0ADAD0489630DFF9A5382A2501AC80D7@cacexc02.americas.cpqcorp.net> -----Original Message----- From: Richard A. O'Keefe [mailto:ok@cs.otago.ac.nz] Sent: Monday, July 14, 2003 3:48 PM To: splint-discuss@cs.virginia.edu Subject: Re: [splint-discuss] Invalid character error I wrote: > The C89 committee > *should* have dealt with this by defining the line continuation > sequence to be backslash, white space*, newline. Peter Busser wrote: In that case it would be different from the way the bakslash is used as a continuation character in e.g. the shell or make. So what? The shell and make should *also* be fixed, but that was a job for the POSIX.2 committee, not the C89 committee. The point is that some mainframe C compilers *do* treat backslash space* newline sensibly, and that the committee should, in the interests of portability, have blessed the practice. There are no C programs which can be broken by this. _______________________________________________ splint-discuss mailing list splint-discuss@cs.virginia.edu http://www.splint.org/mailman/listinfo/splint-discuss From vhamberg at centerfieldtechnology.com Mon Jul 14 19:07:02 2003 From: vhamberg at centerfieldtechnology.com (Vern Hamberg) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Invalid character error In-Reply-To: <200307142247.h6EMlwAV190780@atlas.otago.ac.nz> Message-ID: <5.1.0.14.2.20030714180230.00b9c178@mail.centerfieldtechnology.com> IBM's AS/400 (also called iSeries) would fall into this camp - it seems to honor backslash space* newline as you suggest. Perhaps by its similarity to the mainframes. And fixed length files seem not to have newline characters - have no structural need for them, but consider each record as having an implicit newline. Does this fit your experience. (I'm new to these niceties of C committee standards.) Thanks Vern At 10:47 AM 7/15/2003 +1200, you wrote: >I wrote: > > The C89 committee > > *should* have dealt with this by defining the line continuation > > sequence to be backslash, white space*, newline. > >Peter Busser wrote: > In that case it would be different from the way the bakslash is > used as a > continuation character in e.g. the shell or make. > >So what? The shell and make should *also* be fixed, but that was a job >for the POSIX.2 committee, not the C89 committee. The point is that some >mainframe C compilers *do* treat backslash space* newline sensibly, and >that the committee should, in the interests of portability, have blessed >the practice. There are no C programs which can be broken by this. From Jay.St.Pierre at Colorado.EDU Wed Jul 16 11:52:02 2003 From: Jay.St.Pierre at Colorado.EDU (Jay A. St. Pierre) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] boolean types Message-ID: According to the Splint 3.1.1 manual: Use the -booltype flag to select the type name is used to represent Boolean values. There is no default Boolean type, although bool is used by convention. The names TRUE and FALSE are assumed to represent true and false Boolean values. To change the names of true and false, use -booltrue and -boolfalse. (The Splint distribution includes an implementation of bool, in lib/bool.h. However, it isn't necessary to use this implementation to get the benefits of Boolean checking.) I have the following piece of code: 1 #define FALSE 0 2 #define TRUE 1 3 4 typedef int bool_t; 5 6 int main(void) 7 { 8 bool_t boolean1 = FALSE; 9 bool_t boolean2 = TRUE; 10 11 if (!boolean1) 12 boolean1 = TRUE; 13 14 if (boolean2) 15 boolean2 = FALSE; 16 17 return(0); 18 } When I run splint 3.1.1 against it, I get: % splint -booltype bool_t -booltrue TRUE booltest.c Splint 3.1.1 --- 20 May 2003 booltest.c: (in function main) booltest.c:9:22: Variable boolean2 initialized to type int, expects bool_t: 1 To make bool and int types equivalent, use +boolint. booltest.c:12:5: Assignment of int to bool_t: boolean1 = 1 Finished checking --- 2 code warnings The result is the same without the -booltrue argument. However, if TRUE is defined to (!FALSE), then it works fine. It would seem not to matter what -booltrue and -boolfalse are set to. Am I doing something wrong, or is there a bug here? My desire would be that TRUE could be defined as either "1" or "(!FALSE)". Thanks. -Jay From Jay.St.Pierre at Colorado.EDU Tue Jul 15 15:38:26 2003 From: Jay.St.Pierre at Colorado.EDU (Jay A. St. Pierre) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] boolean types Message-ID: According to the Splint 3.1.1 manual: Use the -booltype flag to select the type name is used to represent Boolean values. There is no default Boolean type, although bool is used by convention. The names TRUE and FALSE are assumed to represent true and false Boolean values. To change the names of true and false, use -booltrue and -boolfalse. (The Splint distribution includes an implementation of bool, in lib/bool.h. However, it isn't necessary to use this implementation to get the benefits of Boolean checking.) I have the following piece of code: 1 #define FALSE 0 2 #define TRUE 1 3 4 typedef int bool_t; 5 6 int main(void) 7 { 8 bool_t boolean1 = FALSE; 9 bool_t boolean2 = TRUE; 10 11 if (!boolean1) 12 boolean1 = TRUE; 13 14 if (boolean2) 15 boolean2 = FALSE; 16 17 return(0); 18 } When I run splint 3.1.1 against it, I get: % splint -booltype bool_t -booltrue TRUE booltest.c Splint 3.1.1 --- 20 May 2003 booltest.c: (in function main) booltest.c:9:22: Variable boolean2 initialized to type int, expects bool_t: 1 To make bool and int types equivalent, use +boolint. booltest.c:12:5: Assignment of int to bool_t: boolean1 = 1 Finished checking --- 2 code warnings The result is the same withouth the -booltrue argument. However, if TRUE is defined to (!FALSE), then it works fine. It would seem not to matter what -booltrue and -boolfalse are set to. Am I doing something wrong, or is there a bug here? My desire would be that TRUE could be defined as either "1" or "(!FALSE)". Thanks. -Jay From roland.illig at gmx.de Sat Jul 19 07:48:57 2003 From: roland.illig at gmx.de (Roland Illig) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] boolean types In-Reply-To: References: Message-ID: <20030719114857.GA5016@burse.uni-hamburg.de> On Tue, Jul 15, 2003 at 01:38:26PM -0600, Jay A. St. Pierre wrote: > 1 #define FALSE 0 > 2 #define TRUE 1 > > 4 typedef int bool_t; > 5 What about this:? typedef int boolean; /* the name bool_t is reserved by C99 or POSIX */ #define FALSE ((boolean) 0) #define TRUE ((boolean) 1) /* Roland */ From Jay.St.Pierre at Colorado.EDU Sat Jul 19 17:35:18 2003 From: Jay.St.Pierre at Colorado.EDU (Jay A. St. Pierre) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] boolean types In-Reply-To: <20030719114857.GA5016@burse.uni-hamburg.de> Message-ID: On Sat, 19 Jul 2003, Roland Illig wrote: > On Tue, Jul 15, 2003 at 01:38:26PM -0600, Jay A. St. Pierre wrote: > > 1 #define FALSE 0 > > 2 #define TRUE 1 > > > > 4 typedef int bool_t; > > 5 > > What about this:? > > typedef int boolean; /* the name bool_t is reserved by C99 or POSIX */ > > #define FALSE ((boolean) 0) > #define TRUE ((boolean) 1) That would certainly work, but the problem is that our legacy code uses the vxWorks definitions of FALSE?(0) and TRUE (1). Without mandating a code change across all the modules to ensure inclusion of our redefinition, we can't seem to use splint to check booleans. bool_t was the posix-compliant type name that we conditionally defined if it wasn't already (we use several different compilers, depending on the target). So my question remains: should splint be able to recognize TRUE defined as just plain (1) as a boolean? I.e, is there a bug in the current release? In the end, we may adjust our code so that we can use splint effectively on booleans, but I think that there may be either a bug in splint or its documentation which should ultimately be corrected regardless of what our particular group decides to do. -Jay PS: I have been unable to compile the latest CVS version of splint on our Sun workstations, so I haven't been able to see if this problem is "fixed" in the CVS head. From niall at lastminute.com Tue Jul 22 07:18:04 2003 From: niall at lastminute.com (Niall Dalton) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs Message-ID: <1058872683.5190.418.camel@localhost.localdomain> Hi, I'm just starting on a new piece of code, developing on a 32 bit machine. I'd like to make sure that the code does not make any assumptions that would cause problems on a 64 bit machine. Splint does check a number of things that will prevent mistakes, not doesn't seem to catch something like: long L = 0xFFFFFFF0L; which, if are want L to have the last four bits set to 0 and everything else set to 1, only works on a 32 bit machine. Is there a way to get splint to catch such errors? Are there other such things that will break on a 64 bit machine that splint does not catch? Best regards Niall From mne at mosaic-ag.com Tue Jul 22 08:59:06 2003 From: mne at mosaic-ag.com (Miroslaw Dobrzanski-Neumann) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <1058872683.5190.418.camel@localhost.localdomain> References: <1058872683.5190.418.camel@localhost.localdomain> Message-ID: <20030722125906.GB1496@mailsrv.mosaic-ag.com> On Tue, Jul 22, 2003 at 12:18:04PM +0100, Niall Dalton wrote: > Hi, > > I'm just starting on a new piece of code, developing on a 32 bit > machine. I'd like to make sure that the code does not make any > assumptions that would cause problems on a 64 bit machine. > Splint does check a number of things that will prevent mistakes, > not doesn't seem to catch something like: > > long L = 0xFFFFFFF0L; > > which, if are want L to have the last four bits set to 0 and everything > else set to 1, only works on a 32 bit machine. I'm using the following code to exress it: long L = ~0xful; > Is there a way to get splint to catch such errors? Are there other such > things that will break on a 64 bit machine that splint does not catch? I don't know -- Miros?aw Dobrza?ski-Neumann E-mail: mne@mosaic-ag.com This message is utf-8 encoded From niall at lastminute.com Tue Jul 22 09:27:33 2003 From: niall at lastminute.com (Niall Dalton) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <20030722125906.GB1496@mailsrv.mosaic-ag.com> References: <1058872683.5190.418.camel@localhost.localdomain> <20030722125906.GB1496@mailsrv.mosaic-ag.com> Message-ID: <1058880452.5190.426.camel@localhost.localdomain> On Tue, 2003-07-22 at 13:59, Miroslaw Dobrzanski-Neumann wrote: > > long L = 0xFFFFFFF0L; > > > > which, if are want L to have the last four bits set to 0 and everything > > else set to 1, only works on a 32 bit machine. > > I'm using the following code to exress it: > > long L = ~0xful; Yes, I know that works on both 32 and 64 bit. But, I'm interested in trying to catch errors I haven't thought of up front, so I can improve the code while its still cheap to do so (asap after I/my team first write it). niall From vhamberg at centerfieldtechnology.com Tue Jul 22 09:30:56 2003 From: vhamberg at centerfieldtechnology.com (Vern Hamberg) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <1058872683.5190.418.camel@localhost.localdomain> Message-ID: <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> FWIW, the iSeries (AS/400) implementation of "long" is 4 bytes, same as "int". And this is a fully 64-bit RISC platform since the mid-90's. An 8-byte integer is called "long long". The standard, I believe, says that a "long" must be at least as many bytes as an "int" - it can be the same size. Are there 64-bit systems where a "long" is 8 bytes? Vern At 12:18 PM 7/22/2003 +0100, you wrote: >Hi, > >I'm just starting on a new piece of code, developing on a 32 bit >machine. I'd like to make sure that the code does not make any >assumptions that would cause problems on a 64 bit machine. >Splint does check a number of things that will prevent mistakes, >not doesn't seem to catch something like: > >long L = 0xFFFFFFF0L; > >which, if are want L to have the last four bits set to 0 and everything >else set to 1, only works on a 32 bit machine. > >Is there a way to get splint to catch such errors? Are there other such >things that will break on a 64 bit machine that splint does not catch? > >Best regards >Niall From niall at lastminute.com Tue Jul 22 09:53:02 2003 From: niall at lastminute.com (Niall Dalton) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> References: <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> Message-ID: <1058881982.5190.435.camel@localhost.localdomain> On Tue, 2003-07-22 at 14:30, Vern Hamberg wrote: > FWIW, the iSeries (AS/400) implementation of "long" is 4 bytes, same as > "int". And this is a fully 64-bit RISC platform since the mid-90's. An > 8-byte integer is called "long long". Interesting - I've never used an iSeries. That is what is commonly called an LLP64 model - long long and pointer are 64 bits. There are also ILP64 (int, long and pointer are 64 bit - such as on Cray machines), and LP64 (int is 32, long is 64 and pointer is 64) models. > The standard, I believe, says that a > "long" must be at least as many bytes as an "int" - it can be the same > size. Yes, that is my understanding as well. My example was one where the code depended on long being 32 bits, which is a bug in my view. > Are there 64-bit systems where a "long" is 8 bytes? LP64 systems include Sparc (assuming one compiles against the 64 bit mode), Alpha and IA-64. niall From mne at mosaic-ag.com Tue Jul 22 10:06:52 2003 From: mne at mosaic-ag.com (Miroslaw Dobrzanski-Neumann) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> References: <1058872683.5190.418.camel@localhost.localdomain> <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> Message-ID: <20030722140652.GC1496@mailsrv.mosaic-ag.com> On Tue, Jul 22, 2003 at 08:30:56AM -0500, Vern Hamberg wrote: > FWIW, the iSeries (AS/400) implementation of "long" is 4 bytes, same as > "int". And this is a fully 64-bit RISC platform since the mid-90's. An > 8-byte integer is called "long long". The standard, I believe, says that a > "long" must be at least as many bytes as an "int" - it can be the same > size. Are there 64-bit systems where a "long" is 8 bytes? AIX4 / AIX5 OSF/1, TrueUnix SunOS -- Miros?aw Dobrza?ski-Neumann E-mail: mne@mosaic-ag.com This message is utf-8 encoded From vhamberg at centerfieldtechnology.com Tue Jul 22 11:14:11 2003 From: vhamberg at centerfieldtechnology.com (Vern Hamberg) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <1058881982.5190.435.camel@localhost.localdomain> References: <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> Message-ID: <5.1.0.14.2.20030722095131.02b02ff8@mail.centerfieldtechnology.com> Niall - FYI iSeries is a bit of a strange beast - pointers are not exactly the same as on Unix systems - they are actually 16-byte monsters above the abstraction layer (called MI, or machine interface, which gives hardware independence). The system is object-based, and there are actually around 10 types of pointers - only 1 or 2 of these are the pointers we know in C. Only specific operations can be used against a specific type of object - *FILE cannot be executed, ever - that takes a *PGM. And you cannot add records to a *PGM - only to a *FILE. (special keywords all start with an asterisk) I just noticed that we (iSeries developers) have a choice of data model - *LLP64, which is what you described, and *P128, which is the native one (sizes of int, long, pointer are 4, 4, 16, respectively). We (the company where I work) never use the *LLP64 option in our products - I think that's to facilitate porting. There's a new memory model now, too, that is a space of data associated with each program (task?). The native model is called single-level-storage - it considers all CPU and disk as one large memory space - no segments and offsets for any development that we as customers and ISVs can do. Hope that is interesting and/or useful. Vern At 02:53 PM 7/22/2003 +0100, you wrote: >On Tue, 2003-07-22 at 14:30, Vern Hamberg wrote: > > FWIW, the iSeries (AS/400) implementation of "long" is 4 bytes, same as > > "int". And this is a fully 64-bit RISC platform since the mid-90's. An > > 8-byte integer is called "long long". > >Interesting - I've never used an iSeries. That is what is commonly >called an LLP64 model - long long and pointer are 64 bits. -SNIP- From niall at lastminute.com Tue Jul 22 12:05:52 2003 From: niall at lastminute.com (Niall Dalton) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <5.1.0.14.2.20030722095131.02b02ff8@mail.centerfieldtechnology.com> References: <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030722095131.02b02ff8@mail.centerfieldtechnology.com> Message-ID: <1058889952.5190.459.camel@localhost.localdomain> On Tue, 2003-07-22 at 16:14, Vern Hamberg wrote: > Hope that is interesting and/or useful. Very cool stuff, I've never worked on a machine remotely like that. Is there some online documentation on all this stuff? A quick search didn't turn up much at IBM. Thanks, niall From vhamberg at centerfieldtechnology.com Tue Jul 22 12:25:10 2003 From: vhamberg at centerfieldtechnology.com (Vern Hamberg) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Splint to check for 64 bit bugs In-Reply-To: <1058889952.5190.459.camel@localhost.localdomain> References: <5.1.0.14.2.20030722095131.02b02ff8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030722082245.0239ccf8@mail.centerfieldtechnology.com> <5.1.0.14.2.20030722095131.02b02ff8@mail.centerfieldtechnology.com> Message-ID: <5.1.0.14.2.20030722112136.02bba7d8@mail.centerfieldtechnology.com> Niall Here's a site that may help with porting and the architecture, etc. It is, of course, pushing the IBM line a bit, but it's good information. General entry point for iSeries is . I do know of a couple web sites where a person can get on a machine for free, if you're interested. Am glad to discuss this further, off-list if you prefer. Cheers Vern At 05:05 PM 7/22/2003 +0100, you wrote: >On Tue, 2003-07-22 at 16:14, Vern Hamberg wrote: > > Hope that is interesting and/or useful. > >Very cool stuff, I've never worked on a machine remotely like that. >Is there some online documentation on all this stuff? A quick search >didn't turn up much at IBM. > >Thanks, >niall From sjl at zepler.org Tue Jul 22 23:04:38 2003 From: sjl at zepler.org (Simon Liddington) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Comparison of short to long int of same sign should be ok with -relax-quals Message-ID: <200307231504.38300.sjl@zepler.org> Hi folks, I get this: src/DataServices/src/Database/src/dsdbm_ReadFields.c:70:9: Operands of != have incompatible types (unsigned short int, unsigned int): fieldLocation.maxNumberOfElements != 1U To ignore type qualifiers in type comparisons use +ignorequals. I don't see a problem with comparing ints with the signedness but of different sizes since there can be no aliasing of values like with a signed and unsigned compare. Also the documentation for -relax-quals says : Report qualifier mismatches only if dangerous (information may be lost since a larger type is assigned to (or passed as) a smaller one or a comparison uses signed and unsigned values.) So is it a bug or an undesirable (at least in my opinion) feature! Simon Liddington From kjdyck at hotmail.com Wed Jul 23 10:19:18 2003 From: kjdyck at hotmail.com (Ken Dyck) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Not completely defined? Message-ID: I have the following code that dynamically allocates an array of arrays. It first allocates an array of pointers, setting them all to NULLs. For each pointer, it checks a condition, exiting if there is an error, then allocates an array of longs, filling it with values. // test1.c #include typedef /*@only@*/ /*@null@*/ long* longptr; static void free_arr(/*@only@*/ /*@null@*/ longptr *arr, int size) { int i; if (arr) { for(i=0; i splint test1.c Splint 3.1.1 --- 02 May 2003 test1.c: (in function foo) test1.c:35:13: Passed storage arr not completely defined (*arr is undefined): free_arr (arr, ...) Storage derivable from a parameter, return value or global is not defined. Use /*@out@*/ to denote passed or returned storage which need not be defined. (Use -compdef to inhibit warning) test1.c:22:2: Storage *arr allocated test1.c:42:13: Passed storage arr not completely defined (*(arr[]) is undefined): free_arr (arr, ...) test1.c:40:3: Storage *(arr[]) allocated test1.c:53:11: Passed storage arr not completely defined (*arr is undefined): free_arr (arr, ...) test1.c:22:2: Storage *arr allocated Finished checking --- 3 code warnings I'm confused by these warnings. In the first for loop, all the elements of arr[] are defined to NULL. Why does splint warn me that it hasn't been defined when I return from line 35? How do I eliminate the warning without -compdef (I want it to perform the check elsewhere)? Is there a special annotation that I need to use? I am new to splint and have not yet finished reading the manual, but in the parts that I have read I have not found anything that clears this up for me. I'm using splint 3.1.1 on cygwin. Ken From sjl at zepler.org Wed Jul 23 19:26:17 2003 From: sjl at zepler.org (Simon Liddington) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Arbitrary integral types Message-ID: <200307241126.17314.sjl@zepler.org> Why don't the arbitrary integral types follow the same checking as for short/long ints? Here's an example #include static void func(uint16_t i) { i = (uint16_t)1; } static void func2(unsigned short i) { i = (unsigned short)1; } int main(void) { uint32_t i = (uint32_t)1; unsigned long i2 = 1UL; func(i); func2(i2); return 0; } liddins@ws1613:~/temp% splint -I /usr/include/linux -sys-dirs "/usr/include/linux" -checks -iso-reserved +enum-int +char-int +relax-quals -decl-undef -export-local -nest-comment +skip-sys-headers test-splint.c Splint 3.1.1 --- 07 Jul 2003 test-splint.c: (in function main) test-splint.c:20:10: Function func2 expects arg 1 to be unsigned short int gets unsigned long int: i2 To ignore type qualifiers in type comparisons use +ignorequals. Finished checking --- 1 code warning surely I should get a similar error for the func() call as the func2() call Because of this I have changed to using -D compiler/splint defines for all these types to get the checking back which is not ideal. Simon Liddington From j.schmidt at baumueller-kamenz.de Thu Jul 24 03:23:20 2003 From: j.schmidt at baumueller-kamenz.de (Jan Schmidt) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Please report bug to splint-bug@splint.org Message-ID: Hello, I used Splint 3.1.1 --- 20 May 2003 to check void test () { unsigned short int a; a = sizeof(a) / sizeof(int); //line 199 } result in typenschild.c:199:3: Assignment of arbitrary unsigned integral type to unsigned short int: a = sizeof((a)) / sizeof(int) To ignore type qualifiers in type comparisons use +ignorequals. and /*@+ignorequals@*/ a = sizeof(a) / sizeof(int); //line 199 /*@-ignorequals@*/ result in typenschild.c:199:3: Assignment of arbitrary unsigned integral type to unsigned short int: a = sizeof((a)) / sizeof(int) typenschild.c:199:31: *** Internal Bug at llerror.c:918: No hint available, flag ignorequals is already set. [errno: 25] *** Please report bug to splint-bug@splint.org *** (attempting to continue, results may be incorrect) From ml at proustmedia.de Thu Jul 24 17:27:05 2003 From: ml at proustmedia.de (Fabrice Haberer-Proust) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] Undefined field Message-ID: <20030724232705.284b8e97.ml@proustmedia.de> Hi, I have a problem that was already discussed in this list (www.splint.org/pipermail/splint-discuss/2002-December/000005.html) but the solutions provided at this time do not seem to work for me. Here (a simplified version of) my code: 1 #include 2 3 typedef struct { 4 int *nnext; 5 } 6 set; 7 8 /*@null@*/ set *set__new() 9 { 10 int x; 11 12 set *set = malloc(sizeof(*set)); 13 14 if (NULL == set) { 15 return NULL; 16 } 17 18 set->nnext = malloc((size_t) 1000 * sizeof(int)); 19 20 if (set->nnext == (int *) NULL) { 21 set->nnext = NULL; 22 free(set); 23 set = NULL; 24 } else { 25 26 for (x = 0 ; x < 1000 ; x++) { 27 set->nnext[x] = -1; 28 } 29 30 } 31 32 return set; 33 } Splint thinks that set->nnext is not defined : splint.c: (in function set__new) splint.c:32:14: Returned storage *set contains 1 undefined field: nnext Storage derivable from a parameter, return value or global is not defined. Use /*@out@*/ to denote passed or returned storage which need not be defined. (Use -compdef to inhibit warning) I first tried to replace the malloc call by a calloc call, since it fills the newly allocated memory with zeros, but it makes no difference for Splint. As suggested, I tried then to add the Splint comments /*@+forloopexec@*/ and /*@=forloopexec@*/ to the lines 25 and 29. But I get the same warning. I also executed Splint with the command line parameters +loopexec and then +forloopexec, without success. Of course, adding /*@out@*/ before "int *nnext;" in the type declaration of set is not a solution, as Splint then considers the variable "set" is not defined. Is there a way to avoid this warning without preventing Splint to detect real errors? I am using Splint 3.1.1 on an Alpha and Splint 3.0.1.6 on an i386, both running Linux Thank you in advance, Fabrice Haberer-Proust Proust Media Kerngasse 3/1 79576 Weil am Rhein Germany From evans at cs.virginia.edu Thu Jul 24 21:04:19 2003 From: evans at cs.virginia.edu (David Evans) Date: Wed Mar 22 17:10:11 2006 Subject: [splint-discuss] boolean types In-Reply-To: References: Message-ID: On Tue, 15 Jul 2003, Jay A. St. Pierre wrote: > ... > When I run splint 3.1.1 against it, I get: > > % splint -booltype bool_t -booltrue TRUE booltest.c > Splint 3.1.1 --- 20 May 2003 > > booltest.c: (in function main) > booltest.c:9:22: Variable boolean2 initialized to type int, expects bool_t: 1 > To make bool and int types equivalent, use +boolint. > booltest.c:12:5: Assignment of int to bool_t: boolean1 = 1 > Finished checking --- 2 code warnings > > The result is the same withouth the -booltrue argument. However, > if TRUE is defined to (!FALSE), then it works fine. It would > seem not to matter what -booltrue and -boolfalse are set to. > > Am I doing something wrong, or is there a bug here? My desire > would be that TRUE could be defined as either "1" or "(!FALSE)". > The reason splint reports a warning here is that the unspecified macro constant TRUE is expanded. Hence, when checking the assignment splint see's the 1 replacement instead of TRUE and reports the warning. The solution is to either use the +allmacros flag so that the macros are not expanded, or to add declarations for them: typedef int bool_t; /*@constant bool_t FALSE@*/ #define FALSE 0 /*@constant bool_t TRUE@*/ #define TRUE ((bool_t) 1) --- Dave From roland at die.burse.uni-hamburg.de Sat Jul 26 16:12:33 2003 From: roland at die.burse.uni-hamburg.de (Roland Illig) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] /*@out@*/ parameters and ioctl Message-ID: <20030726221233.A3501@gurke.burse.uni-hamburg.de> Hi, I just tried to do this: ioctl(cdrom, CDROMREADTOCHDR, /*@out@*/ &toc); Splint reported a parse error. Especially for the ioctl function this syntax would be great, as it would be very hard to check which parameters are to be modifies for which ioctl command. Roland From kenny.stuart at btinternet.com Mon Jul 28 19:16:52 2003 From: kenny.stuart at btinternet.com (Kenny Stuart) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question Message-ID: Hi all, Well I'm new to Splint and to this list, I've read the user guide and had a quick browse through the archive but can't work out what I'm doing wrong, please help. %% Given the following example code: #include /*@-fcnuse@*/ struct Tomato { int a, b, c; }; typedef /*@only@*/ /*@null@*/ struct Tomato* TOMATO; static TOMATO Tomato_create( void ) { TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); if( tomato != NULL ) { tomato->a= tomato->b= tomato->c= 0; } return tomato; } %% and I run Splint thus: > splint +checks test.c Splint 3.1.1 --- 12 April 2003 test.c: (in function Tomato_create) test.c(43,10): Returned storage *tomato contains 3 undefined fields: a, b, c Storage derivable from a parameter, return value or global is not defined. Use /*@out@*/ to denote passed or returned storage which need not be defined. (Use -compdef to inhibit warning) Finished checking --- 1 code warning %% why am I getting the above warning? %% the user guide would appear to indicate that this should not be so! The following sentence is verbatim from Pg.25 [section 5.1 para.3] of the Splint user guide: For example, if p is a pointer to a structure, p is completely defined if the value of p is NULL, or if every Field of the structure p points to is completely defined. also note that near the end of page 26 it states that the basic memory allocator, malloc, is declared: @only@ @null@ void *malloc (size_t size); */ TIA for any assistance. -- Kenny. From roland.illig at gmx.de Thu Jul 31 07:05:43 2003 From: roland.illig at gmx.de (Roland Illig) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: References: Message-ID: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > Hi all, > > Well I'm new to Splint and to this list, I've read the user guide and had a > quick browse through the archive but can't work out what I'm doing wrong, > please help. > > %% Given the following example code: > > #include > > /*@-fcnuse@*/ > > struct Tomato { int a, b, c; }; > typedef /*@only@*/ /*@null@*/ struct Tomato* TOMATO; > > static TOMATO Tomato_create( void ) > { > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > if( tomato != NULL ) { > tomato->a= tomato->b= tomato->c= 0; > } tomato->a = 0; tomato->b = 0; tomato->c = 0; > > return tomato; > } > > %% and I run Splint thus: > > > splint +checks test.c > > Splint 3.1.1 --- 12 April 2003 > > test.c: (in function Tomato_create) > test.c(43,10): Returned storage *tomato contains 3 undefined fields: a, b, c > Storage derivable from a parameter, return value or global is not defined. > Use /*@out@*/ to denote passed or returned storage which need not be > defined. > (Use -compdef to inhibit warning) > > Finished checking --- 1 code warning > > %% why am I getting the above warning? > %% the user guide would appear to indicate that this should not be so! > > The following sentence is verbatim from Pg.25 [section 5.1 para.3] of the > Splint user guide: > For example, if p is a pointer to a structure, p is completely defined if > the value of p is NULL, or if every Field of the structure p points to is > completely defined. The fields are completely defined when they are assigned a value. The other error message is: spl.c:10:10: Name tomato is reserved for future library extensions. Functions beginning with "is" or "to" and a lowercase letter may be added to . (ISO99:7.26.2) Internal name is reserved for system in ISO C99 standard (this should not be necessary unless you are worried about C library implementations that violate the standard and use macros). (Use either -isoreservedinternal or -namechecks to inhibit warning) Roland From Ralf.Wildenhues at gmx.de Thu Jul 31 07:49:12 2003 From: Ralf.Wildenhues at gmx.de (Ralf Wildenhues) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> References: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> Message-ID: <20030731114912.GA10492@iam.uni-bonn.de> * Roland Illig wrote on Thu, Jul 31, 2003 at 01:05:43PM CEST: > On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > > > > #include > > > > /*@-fcnuse@*/ > > > > struct Tomato { int a, b, c; }; > > typedef /*@only@*/ /*@null@*/ struct Tomato* TOMATO; > > > > static TOMATO Tomato_create( void ) > > { > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); Two problems here: In C code, it is rather unfortunate to cast the return value from malloc, as converting von 'void *' to any other pointer type is valid without a cast (unlike C++). Moreover, the cast usually hides compiler complaints when converting from (malloc being implicitly declared as returning) int to a pointer type (which is a bug!). Solution: #include above, and omit the cast here. > > if( tomato != NULL ) { > > tomato->a= tomato->b= tomato->c= 0; > > } > tomato->a = 0; > tomato->b = 0; > tomato->c = 0; Actually, these are potential NULL dereferences (assuming you meant them to be after the closing brace. The original problem is kind of a limitation of splint[1], easily circumvented by explicitly returning NULL in case the malloc failed. > > > > return tomato; > > } Regards, Ralf [1] actually, if memory serves me right, it used to be the case splint (or lclint, as it was then) would recognize this correctly. Can anyone confirm this? From mne at mosaic-ag.com Thu Jul 31 09:10:02 2003 From: mne at mosaic-ag.com (Miroslaw Dobrzanski-Neumann) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: <20030731114912.GA10492@iam.uni-bonn.de> References: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> <20030731114912.GA10492@iam.uni-bonn.de> Message-ID: <20030731131002.GA19021@mailsrv.mosaic-ag.com> On Thu, Jul 31, 2003 at 01:49:12PM +0200, Ralf Wildenhues wrote: > * Roland Illig wrote on Thu, Jul 31, 2003 at 01:05:43PM CEST: > > On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > > > > > > #include > > > > > > /*@-fcnuse@*/ > > > > > > struct Tomato { int a, b, c; }; > > > typedef /*@only@*/ /*@null@*/ struct Tomato* TOMATO; > > > > > > static TOMATO Tomato_create( void ) > > > { > > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > > Two problems here: In C code, it is rather unfortunate to cast the > return value from malloc, as converting von 'void *' to any other > pointer type is valid without a cast (unlike C++). Moreover, the cast > usually hides compiler complaints when converting from (malloc being > implicitly declared as returning) int to a pointer type (which is a > bug!). Solution: #include above, and omit the cast here. I use to use the following memory allocation scheme: #define NEW(t) ((t *)(malloc (sizeof (t)))) note that I use here the cast which forces the compiler to check for bad assignments as in: t *var = NEW (t) /* GOOD */ x *var = NEW (t) /* BAD, compiler complains about */ x *var = malloc (sizeof t) does not catch this kind of errors Regards -- Miros?aw Dobrza?ski-Neumann E-mail: mne@mosaic-ag.com This message is utf-8 encoded From Ralf.Wildenhues at gmx.de Thu Jul 31 09:31:57 2003 From: Ralf.Wildenhues at gmx.de (Ralf Wildenhues) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: <20030731131002.GA19021@mailsrv.mosaic-ag.com> References: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> <20030731114912.GA10492@iam.uni-bonn.de> <20030731131002.GA19021@mailsrv.mosaic-ag.com> Message-ID: <20030731133157.GA5027@iam.uni-bonn.de> * Miroslaw Dobrzanski-Neumann wrote on Thu, Jul 31, 2003 at 03:10:02PM CEST: > On Thu, Jul 31, 2003 at 01:49:12PM +0200, Ralf Wildenhues wrote: > > > On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > > > > > > > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > > > > Two problems here: In C code, it is rather unfortunate to cast the > > return value from malloc, as converting von 'void *' to any other > > pointer type is valid without a cast (unlike C++). Moreover, the cast > > usually hides compiler complaints when converting from (malloc being > > implicitly declared as returning) int to a pointer type (which is a > > bug!). Solution: #include above, and omit the cast here. > > I use to use the following memory allocation scheme: > #define NEW(t) ((t *)(malloc (sizeof (t)))) > > note that I use here the cast which forces the compiler to check for bad > assignments as in: > > t *var = NEW (t) /* GOOD */ > x *var = NEW (t) /* BAD, compiler complains about */ > > x *var = malloc (sizeof t) does not catch this kind of errors Well, your macro always makes me think of C++. So, for one thing, I'd be confused (do you define a DELETE also?), for another it doesn't catch the 'stdlib.h inclusion forgotten' bug, for another it does not work with complex types (try something like 'int (*)[]'). Last but not least, it is easy to just get into the habit of using foobar_type *foo = malloc(nelem * sizeof *foo); which prevents this kind of mistake. Regards, Ralf From mne at mosaic-ag.com Thu Jul 31 10:37:14 2003 From: mne at mosaic-ag.com (Miroslaw Dobrzanski-Neumann) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: <20030731133157.GA5027@iam.uni-bonn.de> References: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> <20030731114912.GA10492@iam.uni-bonn.de> <20030731131002.GA19021@mailsrv.mosaic-ag.com> <20030731133157.GA5027@iam.uni-bonn.de> Message-ID: <20030731143714.GB19021@mailsrv.mosaic-ag.com> On Thu, Jul 31, 2003 at 03:31:57PM +0200, Ralf Wildenhues wrote: > * Miroslaw Dobrzanski-Neumann wrote on Thu, Jul 31, 2003 at 03:10:02PM CEST: > > On Thu, Jul 31, 2003 at 01:49:12PM +0200, Ralf Wildenhues wrote: > > > > On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > > > > > > > > > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > > > > > > Two problems here: In C code, it is rather unfortunate to cast the > > > return value from malloc, as converting von 'void *' to any other > > > pointer type is valid without a cast (unlike C++). Moreover, the cast > > > usually hides compiler complaints when converting from (malloc being > > > implicitly declared as returning) int to a pointer type (which is a > > > bug!). Solution: #include above, and omit the cast here. > > > > I use to use the following memory allocation scheme: > > #define NEW(t) ((t *)(malloc (sizeof (t)))) > > > > note that I use here the cast which forces the compiler to check for bad > > assignments as in: > > > > t *var = NEW (t) /* GOOD */ > > x *var = NEW (t) /* BAD, compiler complains about */ > > > > x *var = malloc (sizeof t) does not catch this kind of errors > > Well, your macro always makes me think of C++. So, for one thing, I'd > be confused (do you define a DELETE also?), currently I use four macros #define NEW(t) NEW_ARY(1,t) #define NEW_ARY(n,t) ((t *)(malloc ((n) * sizeof (t)))) #define DEL(p) do { if ((p)) free ((p)); (p) = NULL; } while (0) #define DEL_BEEF(p) do { if ((p)) free ((p)); (p) = (void *)(0xdeadbeef); } while (0) > for another it doesn't catch the 'stdlib.h inclusion forgotten' bug, no but it's easy to work around it, maybe in a global project config file which will be included every where static inline void *dummy (void) { return malloc (1); } a better solution is to use the compiler for this job gcc -Wmissing-prototypes xlc -qinfo=pro ... almost every compiler has such an option. > for another it does not work > with complex types (try something like 'int (*)[]'). it is not a solution for all memory allocation problems. It just simplifies 90% of them. > Last but not > least, it is easy to just get into the habit of using > foobar_type *foo = malloc(nelem * sizeof *foo); > which prevents this kind of mistake. I do not rely on an habit which requires me to type the same thing twice but do not verifies my correct usage of it noone prevents me from typing the following buggy code. It's only a typo but detecting it could be a hard job. foobar__type1 *bar; foobar_type *foo = malloc(nelem * sizeof *bar); -- Miros?aw Dobrza?ski-Neumann E-mail: mne@mosaic-ag.com This message is utf-8 encoded From roland.illig at gmx.de Thu Jul 31 10:59:48 2003 From: roland.illig at gmx.de (Roland Illig) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> References: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> Message-ID: <20030731145948.GA17250@gurke.burse.uni-hamburg.de> On Thu, Jul 31, 2003 at 01:05:43PM +0200, Roland Illig wrote: > [... something wrong ...] > > > > static TOMATO Tomato_create( void ) > > { > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > > if( tomato != NULL ) { > > tomato->a= tomato->b= tomato->c= 0; > > } > tomato->a = 0; > tomato->b = 0; > tomato->c = 0; > > > > return tomato; > > } of course, that's really bad. (It seems I didn't read the code properly. You could code it like: static TOMATO Tomato_create(void) { TOMATO result; result = malloc(sizeof *tomato); if (tomato == NULL) { return NULL; } result->a = 0; result->b = 0; result->c = 0; return result; } Roland From subs at klib.fsnet.co.uk Thu Jul 31 11:24:29 2003 From: subs at klib.fsnet.co.uk (Kenny Stuart) Date: Wed Mar 22 17:10:12 2006 Subject: [subs] Re: [splint-discuss] Newbie question In-Reply-To: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> Message-ID: -----Original Message----- From: splint-discuss-admin@cs.virginia.edu [mailto:splint-discuss-admin@cs.virginia.edu]On Behalf Of Roland Illig Sent: 31 July 2003 12:06 To: splint-discuss@cs.virginia.edu Subject: [subs] Re: [splint-discuss] Newbie question On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > Hi all, > > Well I'm new to Splint and to this list, I've read the user guide and had a > quick browse through the archive but can't work out what I'm doing wrong, > please help. > > %% Given the following example code: > > #include > > /*@-fcnuse@*/ > > struct Tomato { int a, b, c; }; > typedef /*@only@*/ /*@null@*/ struct Tomato* TOMATO; > > static TOMATO Tomato_create( void ) > { > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > if( tomato != NULL ) { > tomato->a= tomato->b= tomato->c= 0; > } tomato->a = 0; tomato->b = 0; tomato->c = 0; > > return tomato; > } That might stop splint complaining but the potential NULL dereference would certainly be an unwelcome side-effect. Kenny From subs at klib.fsnet.co.uk Thu Jul 31 15:36:29 2003 From: subs at klib.fsnet.co.uk (Kenny Stuart) Date: Wed Mar 22 17:10:12 2006 Subject: [subs] Re: [splint-discuss] Newbie question In-Reply-To: <20030731114912.GA10492@iam.uni-bonn.de> Message-ID: -----Original Message----- From: splint-discuss-admin@cs.virginia.edu [mailto:splint-discuss-admin@cs.virginia.edu]On Behalf Of Ralf Wildenhues Sent: 31 July 2003 12:49 To: splint-discuss@cs.virginia.edu Subject: [subs] Re: [splint-discuss] Newbie question * Roland Illig wrote on Thu, Jul 31, 2003 at 01:05:43PM CEST: > On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > > > > #include > > > > /*@-fcnuse@*/ > > > > struct Tomato { int a, b, c; }; > > typedef /*@only@*/ /*@null@*/ struct Tomato* TOMATO; > > > > static TOMATO Tomato_create( void ) > > { > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); Two problems here: In C code, it is rather unfortunate to cast the return value from malloc, as converting von 'void *' to any other pointer type is valid without a cast (unlike C++). Moreover, the cast usually hides compiler complaints when converting from (malloc being implicitly declared as returning) int to a pointer type (which is a bug!). Solution: #include above, and omit the cast here. %% Wow, I've not used 'C' for about 10 years, just started using it to take a look at splint and totally forgot about implicit declarations, thanks for the nudge, I just purchased a copy of ISO 9899/1999 for reference and see implicit declarations have thankfully been removed, I like the fact you don't need to explicitly cast from a null pointer to some other pointer type for the reason you've given. I'm not sure I would class conversion of an int to a pointer type as a bug since it is described in the C99 standard as implementation defined, the way I read it, although potentially non-portable, used properly it is likely to yield the desired effect since the C99 standard (sorry, I've just purchased the standard so I'm looking everything up, it'll wear off eventually ;) further states that the mapping functions for converting a pointer to an integer and vice versa are intended to be consistent with the addressing structure of the execution environment, as my example code shows however, it's easy (pre C99 at least) to do it accidentally, I won't be explicitly casting null pointers again :) > > if( tomato != NULL ) { > > tomato->a= tomato->b= tomato->c= 0; > > } > tomato->a = 0; > tomato->b = 0; > tomato->c = 0; Actually, these are potential NULL dereferences (assuming you meant them to be after the closing brace. %% Ah, I see you've already mentioned that. The original problem is kind of a limitation of splint[1], easily circumvented by explicitly returning NULL in case the malloc failed. %% That's a surprise since it explicitly requires multiple return statements, which as best practice suggests, I avoid wherever possible, huh, I was convinced I'd lost my mind and was doing something fundamentally wrong! Does anyone know if that's something that's likely to be addressed? Thanks to all for the feedback, I've no doubt I'm going to be asking more newbie questions as I progress so please bear with me ;) Kenny. From wildenhu at iam.uni-bonn.de Thu Jul 31 09:27:43 2003 From: wildenhu at iam.uni-bonn.de (Ralf Wildenhues) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question In-Reply-To: <20030731131002.GA19021@mailsrv.mosaic-ag.com> References: <20030731110543.GA15845@gurke.burse.uni-hamburg.de> <20030731114912.GA10492@iam.uni-bonn.de> <20030731131002.GA19021@mailsrv.mosaic-ag.com> Message-ID: <20030731132743.GA4933@iam.uni-bonn.de> * Miroslaw Dobrzanski-Neumann wrote on Thu, Jul 31, 2003 at 03:10:02PM CEST: > On Thu, Jul 31, 2003 at 01:49:12PM +0200, Ralf Wildenhues wrote: > > > On Tue, Jul 29, 2003 at 12:16:52AM +0100, Kenny Stuart wrote: > > > > > > > > TOMATO tomato= (TOMATO)malloc( sizeof *tomato ); > > > > Two problems here: In C code, it is rather unfortunate to cast the > > return value from malloc, as converting von 'void *' to any other > > pointer type is valid without a cast (unlike C++). Moreover, the cast > > usually hides compiler complaints when converting from (malloc being > > implicitly declared as returning) int to a pointer type (which is a > > bug!). Solution: #include above, and omit the cast here. > > I use to use the following memory allocation scheme: > #define NEW(t) ((t *)(malloc (sizeof (t)))) > > note that I use here the cast which forces the compiler to check for bad > assignments as in: > > t *var = NEW (t) /* GOOD */ > x *var = NEW (t) /* BAD, compiler complains about */ > > x *var = malloc (sizeof t) does not catch this kind of errors Well, your macro always makes me think of C++. So, for one thing, I'd be confused (do you define a DELETE also?), for another it doesn't catch the 'stdlib.h inclusion forgotten' bug, for another it does not work with complex types (try something like 'int (*)[]'). Last but not least, it is easy to just get into the habit of using foobar_type *foo = malloc(nelem * sizeof *foo); which prevents this kind of mistake. Regards, Ralf From ok at cs.otago.ac.nz Thu Jul 31 21:03:27 2003 From: ok at cs.otago.ac.nz (Richard A. O'Keefe) Date: Wed Mar 22 17:10:12 2006 Subject: [splint-discuss] Newbie question Message-ID: <200308010103.h7113R6P444568@atlas.otago.ac.nz> I use to use the following memory allocation scheme: #define NEW(t) ((t *)(malloc (sizeof (t)))) Bad idea. As already noted, if you forgot to #include , the cast will prevent the warning message you would normally have got. It's also a bad idea because you have to keep mentioning the type over and over and over, and if the variable type changes, the code will break. Better idea: #define new(var) (var) = emalloc(sizeof *(var)) #define new_array(var, n) (var) = emalloc((n) * sizeof *(var)) where emalloc() is a function just like malloc() but which catches errors. Then t *var; new(var); new_array(var, n+1); t *var = NEW (t) /* GOOD */ x *var = NEW (t) /* BAD, compiler complains about */ x *var = malloc (sizeof t) does not catch this kind of errors which amongst other things is why var = malloc(sizeof *var) is better.