From: bjv@shasta.tivoli.com (Brian Vetter)
Newsgroups: comp.unix.programmer
Subject: Re: I am stumped by this one!!!
Date: 30 Jul 92 18:24:38 GMT
Distribution: usa
Organization: TIVOLI Systems

In article <1992Jul27.134826.5592@cbfsb.cb.att.com>, rajeev@cbnewsf.cb.att.com (rajeev.dolas) writes:
|> 
|> 	I realize the error on sizeof instead of strlen() for malloc. But
|> 	I don't think that is the cause of SEGV error. If you look at my
|> 	original posting, you will notice that I am able to copy selected
|> 	characters to cp_line.
|> 
|> 	In my original code I wasn't even using the cp_line. I was reading
|> 	a char pointed to by *pbuf and was writing that to the file. I
|> 	got the SEGV error on the putc()!!! Now I am using fputs() to
|> 	write a string instead of a char and I get the same error on
|> 	fputs(). Also fputs(tmp_line,stdout) works fine while 
|> 	fputs(tmp_line,fp1) does not!!! That's what is driving me nuts.

It looks to me that you have several problems with your code.  First,
the sizeof is a serious problem.  If you look at your code, you'll see that
once you copy more than 4 bytes from the pbuf to cp_line, you will
start overwriting the data you allocated for cp_line.  This can cause
all kinds of unpredictable errors.

Secondly, after you complete your loop "while (*pbuf != '\0')", you
never terminate the cp_line string with a NULL character.  fputs() would
continue writing data after the end of your string (potentially many bytes).

The SEGV message you get is in the malloc code.  fputs() and all of the
stdio functions that write using a FILE * may (and frequently do) call
malloc to keep a buffer so that writes perform better.  In general, when
you get SEGVs and BUSERRs in malloc, it is due to dynamically allocated
buffers being overwritten.  malloc() keeps information about the allocation
pool mixed in with your allocated data so it is easy to confuse.

The bug you are looking for may not even be in the code you have provided.
Based on what I can see here, you must be fairly new to C or to some of the
more common extensions.  I would suggest you get a debug version of malloc
to link against your code or try a commercial product such as Purify.
They can help you find such problems if you aren't familiar enough debugging
dynamic memory bashing code.

As a critique of your code:

pars_wbuf[strlen(pars_wbuf)] = '\0'	Isn't needed - fgets already put the
					null byte at the end - otherwise the
					strlen would fail.

The sizeof is WRONG and your code WILL FAIL if you don't fix it.

It looks like the else clause just strips out the \r character (CR).
Why do the malloc at all?  Why not just copy the data in place? ie:

	for (to=pars_wbuf, from=pars_wbuf; *from; from++) {
		if (*from != '\r') {
			*to++ = *from;
		}
	}
	fputs(pars_wbuf, fp1);

This isn't even optimal since you don't need to do the assignments until
you find the first CR.

|> 	
|> 	I am including the relevant portion of the code to clarify my
|> 	point and not to drive the 2400 baud-ers nuts :-)
|> 
|> 	/* str_comp is my function which returns -1 if match is not found */
|> 	while((fgets(pars_wbuf, 80, fp2) != NULL) &&
|> 		((parse_ret = str_comp(cmp, pars_wbuf)) != 0))
|> 	{
|> 		pars_wbuf[strlen(pars_wbuf)] = '\0';
|> 		pbuf = pars_wbuf;
|> 		cp_line = (char *)malloc(sizeof(strlen(pars_wbuf)));
|> 		strcpy(cp_line, "\0");
|> 		tmp_line = cp_line;
|> 
|> 		if((comp = line_comp(pars_wbuf)) == 0)
|> 			;
|> 		else 
|> 		{
|> 			/* Traverse thru pbuf, skip "
|> 			while(*pbuf != '\0')
|> 			{
|> 				if(*pbuf != 0x0D)
|> 				{
|> 					/* I was writing a char at a time to
|> 					   the file before. This part works
|> 					   on Amdahl but not on a sun.	*/
|> 
|> 					/**
|> 					ch = *pbuf;
|> 					fprintf(stdout, "%c", ch); 
|> 					if((he = putc(ch, fp1)) < 0)
|> 					{
|> 					     printf("pars_conf: Write error\n");
|> 						return(-13);
|> 					}
|> 					**/
|> 
|> 					/* Now I save it to a buffer */
|> 					*cp_line++ = *pbuf;
|> 				}
|> 				*pbuf++;
|> 			}
|> 			/* If I do a fputs to stdout, it works fine */
|> 			/**
|> 			fputs(tmp_line, stdout);
|> 			fflush(stdout);
|> 			**/
|> 
|> 			/* dbxtool shows the following error on this instr -
|> 			 signal SEGV in malloc at 0xf773634
|> 			 malloc+0x150:	st	%o0, [%15]
|> 			 */
|> 			fputs(tmp_line, fp1);
|> 		}
|> 		free(cp_line);
|> 	}
|> 	
|> }