parsing strings / within a filename

B

BMarsh

Hi all,

I have the following piece of code which i've been wrestling with for
sometime, which I attribute, still, to my lack of understanding of
pointers. (this is probably rining alarm bells atm for you seasoned
pro's...).

I am trying to parse a file with the following format:

hostname {
file1;
file2;
file3;
};

Now, i could get this from the BIND source code (OT: named.conf
parsing..) but I really need to crack this myself...

I have the following code:


load_config(char *fn)
{
FILE *fp;
char *host;
char *buf;
int inblock=0;

buf=malloc(1024);
host=malloc(32);

if((fp=fopen(fn,"r+")) < 0)
{
fatal("fopen"); // my own wrapper..
}

memset(buf,'\0',1024);
while(fgets(buf,sizeof(buf),fp)) {
buf[strlen(buf)-1]='\0';
if(*buf == '{') {
inblock=1;
printf("%s",buf);
buf++;
}
}

}

This occasionally segfaults depending on wether I use an array for buf
or a pointer..

I don't even get up to the left brace.. I basically need to gobble up
the next three files, which I think I can do with fgets, blast the
newline and strtok with the semi-colon no problem, but I can't seem to
move through the file!!

Thanks in advance for any help you can provide

Cheers

Bryan.
 
I

infobahn

BMarsh said:
Hi all,

I have the following piece of code which i've been wrestling with for
sometime, which I attribute, still, to my lack of understanding of
pointers.

Correct attribution. Well done.
(this is probably rining alarm bells atm for you seasoned
pro's...).

Yawn. :)

I have the following code:

load_config(char *fn)
{
FILE *fp;
char *host;
char *buf;
int inblock=0;

buf=malloc(1024);
host=malloc(32);

Check that these don't fail.

if(buf == NULL) fatal("buf malloc");
if(host == NULL) fatal("host malloc");
if((fp=fopen(fn,"r+")) < 0)
{
fatal("fopen"); // my own wrapper..
}

memset(buf,'\0',1024);
while(fgets(buf,sizeof(buf),fp)) {

Hold on there, pardnuh. buf is a pointer, not an array. So sizeof(buf)
is going to give you the size of a pointer, which isn't what you want
here. You want the amount of memory you allocated, to which buf points.
That is, 1024.
buf[strlen(buf)-1]='\0';
if(*buf == '{') {
inblock=1;
printf("%s",buf);
buf++;

Ouch. Don't you move that pointer! Find another way around.
 
B

BMarsh

Hi Infobahn..

Danke fuer ihren hilfe. :)

I was of the impression that I could move pointers like so? Can I not
move through that string? Perhaps incrementing the dereferenced pointer
will work? Argh I need to re-pickup herbert schildt's book..

Thanks again

bry.
 
B

BMarsh

Ok - the 2nd coming.

I have the following, and it segfaults...argh...

BTW - MAXBUF is defined as 1024

load_config(char *fn)
{
FILE *fp;
char *host;
char *buf;
int inblock=0;

if((host=malloc(MAXBUF)) == NULL)
fatal("malloc");

if((fbuf=malloc(MAXBUF)) == NULL)
fatal("malloc");

if((fp=fopen(filename,"r+")) < 0) {
fatal("fopen");
}

memset(buf,'\0',MAXBUF);
while(fgets(buf,MAXBUF,fp)) {
fbuf[strlen(buf) -1]='\0';
while(*buf) {
if(*buf == '{') {
inblock=1;
while(*buf != ';') {
*buf++ = *host++;
}
} *buf++;
}
}
printf("host: %s\n",host);

return 0;
}

GDB says the *buf++ = *host++; line is the problem - but I am
essentially doing what strcpy does..

Thanks again... :)

Bryan.
 
D

David Resnick

BMarsh said:
Ok - the 2nd coming.

I have the following, and it segfaults...argh...

BTW - MAXBUF is defined as 1024

load_config(char *fn)
{
FILE *fp;
char *host;
char *buf;
int inblock=0;

if((host=malloc(MAXBUF)) == NULL)
fatal("malloc");

if((fbuf=malloc(MAXBUF)) == NULL)
fatal("malloc");

if((fp=fopen(filename,"r+")) < 0) {
fatal("fopen");
}

memset(buf,'\0',MAXBUF);
while(fgets(buf,MAXBUF,fp)) {
fbuf[strlen(buf) -1]='\0';
while(*buf) {
if(*buf == '{') {
inblock=1;
while(*buf != ';') {
*buf++ = *host++;
}
} *buf++;
}
}
printf("host: %s\n",host);

return 0;
}

GDB says the *buf++ = *host++; line is the problem - but I am
essentially doing what strcpy does..

Thanks again... :)

Bryan.

Here is what you are doing as an example
> 1024 bytes <
^ buf points here

Read a 512 byte line
> 1024 bytes <
^buf points here

Read a 1000 byte line
> 1024 bytes <
^ buf points here

Buf now points outside of the region allocated. The last read overwrote
whatever was after the region allocated by the original malloc. You are
telling fgets that the size of buf is MAXBUF, and so it is from the
original value of buf. But you are advancing buf through the buffer,
but still telling fgets to read up to MAXBUF bytes. The size of the
region allocated by buf has not changed. If you need it to grow, you
could keep calling "realloc" to make it bigger.

Perhaps I'm misreading the above. Are you reading IN TOTAL more than
1024 bytes in all calls to fgets? If so, that is the problem...

This line is also not very defensive:

while(*buf != ';') {

If you are missing a ; you will go until you find one, reading outside
of your allocated space and writing outside your allocated space in .
Perhaps you mean:

while (*buf && *buf != ';')

And then the real problem is probably that

*buf++ = *host++;

Means to be

*host++ = *buf++

The malloc'd memory pointed to by host is never initialized in the
function above, likely contains garbage.

-David
 
F

Flash Gordon

BMarsh said:
Hi Infobahn..

Danke fuer ihren hilfe. :)

It's helpful if you actually quote sufficient of what you are replying
to that we know what you are talking about. I think CBFalconer has
instructions in his sig for how to do something sensible with Google.
I was of the impression that I could move pointers like so? Can I not
move through that string? Perhaps incrementing the dereferenced pointer
will work?

Yes, you can. However, when you have a malloc'd block you need to keep a
record of where it starts. Your code in question was:

| buf=malloc(1024);
| host=malloc(32);
|
| if((fp=fopen(fn,"r+")) < 0)
| {
| fatal("fopen"); // my own wrapper..
| }
|
| memset(buf,'\0',1024);
| while(fgets(buf,sizeof(buf),fp)) {

What will the value of buf be when you get here second time since you
incrememt it bellow?

| buf[strlen(buf)-1]='\0';
| if(*buf == '{') {
| inblock=1;
| printf("%s",buf);
| buf++;
| }
| }

Also, when it comes to freeing the memory later you need the pointer
returned by malloc, realloc or calloc since that is what you pass to free.
> Argh I need to re-pickup herbert schildt's book..

No, you need incinerate that book before it does any further harm.
Search this group for references to it and you will find links to
reviews showing just how many errors it contains. I'm not talking about
typos you might spot, but errors in Schildt's understanding of C that
will mislead you.

I would recomend the FAQ for comp.lang.c (google will find it for you)
and K&R2.
 
C

CBFalconer

BMarsh said:
I was of the impression that I could move pointers like so? Can I
not move through that string? Perhaps incrementing the dereferenced
pointer will work? Argh I need to re-pickup herbert schildt's book..

Lacking any quotes, I have no idea what "like so" means. However
it is highly likely that you have misconceptions due to reading
anything from Schildt, which is generally considered to be
extremely smelly BullSchildt here, and best dried out in the sun
and then burnt.
 
J

Jack Klein

comp.lang.c:

Nobody seems to have pointed out...

Hi all,

I have the following piece of code which i've been wrestling with for
sometime, which I attribute, still, to my lack of understanding of
pointers. (this is probably rining alarm bells atm for you seasoned
pro's...).

I am trying to parse a file with the following format:

hostname {
file1;
file2;
file3;
};

Now, i could get this from the BIND source code (OT: named.conf
parsing..) but I really need to crack this myself...

I have the following code:


load_config(char *fn)
{
FILE *fp;
char *host;
char *buf;
int inblock=0;

buf=malloc(1024);
host=malloc(32);

if((fp=fopen(fn,"r+")) < 0)

What the heck is this!?!

The object fp is a pointer to FILE. It is not an integer or any type
of arithmetic variable. There is something very, very wrong with your
compiler if it even compiles this. It is a constraint violation.

fopen() returns NULL or 0 on failure, and something not zero on
success. And the only valid comparison of a pointer with a scalar
value is for equality or inequality with NULL or 0.

The test should be:

if ((fp = fopen(fn, "r+") == 0)

What compiler are you using that accepted the code as you wrote it
without a diagnostic? It is badly non-conforming.
 
B

BMarsh

Hello all,

Thanks for your replies - All of the string pointer information I
learned years ago was from Schildt, yes... :-(

I think I might have run out of toilet paper - how convenient.....


FAO: Jack Klein - The compiler is gcc 3.4.x on Slackware Linux. I have
been thinking about developing my code on AIX anyway - that compiler
seems to be super strict from what I have seen when compiling certain
packages, etc...

Thanks again - i'll go and bash my head against a brick wall for a
while then fire up amazon - And as you all lambast Schildt's book, do
you have any recommendations apart from K&R2? (I've got that).

Thanks once again

Bry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,161
Messages
2,570,891
Members
47,423
Latest member
henerygril

Latest Threads

Top