Malloc problem with fread() to read file to structure in C


 
Thread Tools Search this Thread
Top Forums Programming Malloc problem with fread() to read file to structure in C
# 8  
Old 02-10-2014
I am using
$ uname -a
$ Linux 3.5.0-44-generic #67-Ubuntu SMP Tue Nov 12 19:36:14 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct student {
        int             roll_num;
        char            *name;
        struct student  *next;
}       *head,          // Pointer to first element in the linked list.
        *temp;          // When creating the linked list, a pointer to current
                        // element in the linked list; when deleting the linked
                        // list, a pointer to the next element in the list.

        // Note that both head and temp are initialzed to NULL pointers because
        // they are declared globally; not on the stack in main().

        // Note also that no linked list elements have been allocated yet (we
        // have allocated two pointers to structures, but no structures);
        // space for structures will be allocated as needed as lines are read
        // from the input file.

int main(int argc, char *argv[]) {
        char            buffer[120];    // input buffer
        FILE            *fptr;          // input stream pointer
        size_t          len;            // length of name
        char            *p;             // pointer to name in buffer[]

        fptr = fopen("INFILE.txt", "r");
        if(fptr == NULL) {
                fprintf(stderr, "%s: fopen(INFILE.txt) failed.\n", argv[0]);
                exit(1);
        }

        // Read input file into a linked list...
        // Note that fgets() reads no more than one line (up to a given number
        // of bytes)from a file; fread() reads a given number of bytes without
        // regard to line boundaries.
        while(fgets(buffer, sizeof(buffer), fptr)) {
                // XXX Should verify that fgets() returned a complete line.
//yifangt                printf("Read input line: %s", buffer);

                // Allocate space for this element of the linked list.
                // Note that using calloc() instead of malloc() initializes
                // temp->next (in the newly allocated structure) to a NULL
                // pointer.  (It also fills any space between structure
                // elements (if there is any) to null bytes.  This isn't
                // important for this example, but can be important if
                // structures are to be examined in a core dump or compared.)
                if(head == NULL)
                        // Create 1st element in the linked list.
                        temp = head = calloc(1, sizeof(struct student));
                else    // Add new element to the end of the linked list.  Note
                        // that the temp->next in the next statement is in the
                        // previous element in the linked list and then temp is
                        // set to a pointer to the (new) current element.
                        temp = temp->next = calloc(1, sizeof(struct student));
                if(temp == NULL) {
                        fprintf(stderr,
                                "%s: calloc() for linked list element failed.\n",
                                argv[0]);
                        exit(2);
                }
                printf("%d bytes allocated at %p for linked list element\n",
                        (int)sizeof(struct student), temp);

                // Convert numeric string at start of buffer to int.
                temp->roll_num = atoi(buffer);

                // skip over number and 1st space to find start of name.
                // XXX Should check for string overflow for badly formed input.
                for(p = buffer; *p++ != ' ';);

                // Allocate space and copy name.  Note that strlen() will
                // include space for the trailing newline character but not for
                // the terminating null byte.  But, we'll replace the newline
                // with a null byte before we copy the name from buffer[] to
                // the space we allocated for name in this linked list element.
                len = strlen(p);
                if((temp->name = malloc(len)) == NULL) {
                        fprintf(stderr, "%s: malloc(%d) for name failed.\n", argv[0], (int)len);
                        exit(3);
                }
                // Change trailing newline to string terminator.
                *(p + len - 1) = '\0';
                // Copy name into allocated space.  Note that len includes the
                // null byte that termiantes the string.
                strncpy(temp->name, p, len);
        printf("%d bytes allocated at %p for name %s\n\n", (int)len,
                        temp->name, temp->name);
        }

        // To get to here, we either hit EOF or detected an I/O error.
        if(ferror(fptr)) {
                fprintf(stderr, "%s: I/O error reading input.\n", argv[0]);
                exit(4);
        }
        fclose(fptr);
       printf("End-of-file found on input.\n");

        // We have now completed reading the input into a linked list.  Note
        // that temp->next (the pointer to the next element in the last element
        // in the linked list) is a NULL pointer.

        // Writing a linked list to a file doesn't make any sense.  The pointers
        // in the structures have no meaning in a file and won't be valid if
        // read back into another process.

        // For this example, we'll just print the data from the linked list and
        // free the space reserved for the elements after each element is
        // printed.  Obviously, we could reformat the data and save it in a file
        // but for this demo, showing what we have in the linked list seems more
        // important.

        printf("\nPrinting list element located at %p:\n", head);
        while(head) {
                printf("roll_num: %d\tname: %s\n", head->roll_num, head->name);
//yifangt        printf("Freeing name (%p) and list element (%p) space.\n",
        //                head->name, head);
                free(head->name);
                // Note that we can't reference head->next after we free head,
                // so we need to save the pointer to the next element before we
                // free the current element.
                temp = head->next;
                free(head->next);
                head = temp;
                // Note that head now points to the 1st remaining element of
                // the linked list again, if there are any elements left.  It is
                // a NULL pointer if no elements remain in the list.
        }

        // We have now freed all of the space we allocated for the linked list
        // elements and the space we allocated for the names associated with
        // each element in the linked list.
        return(0);
}

# 9  
Old 02-10-2014
When I run the code you showed us in message #8 in this thread, the output I get is:
Code:
24 bytes allocated at 0x10a000890 for linked list element
7 bytes allocated at 0x10a0008b0 for name Angola

24 bytes allocated at 0x10a0008c0 for linked list element
10 bytes allocated at 0x10a0008e0 for name Bangalore

24 bytes allocated at 0x10a0008f0 for linked list element
6 bytes allocated at 0x10a000910 for name Cairo

24 bytes allocated at 0x10a000920 for linked list element
7 bytes allocated at 0x10a000940 for name Dallas

24 bytes allocated at 0x10a000950 for linked list element
9 bytes allocated at 0x10a000970 for name Edmonton

24 bytes allocated at 0x10a000980 for linked list element
6 bytes allocated at 0x10a0009a0 for name Fargo

24 bytes allocated at 0x10a0009b0 for linked list element
8 bytes allocated at 0x10a0009d0 for name Georgia

24 bytes allocated at 0x10a0009e0 for linked list element
8 bytes allocated at 0x10a000a00 for name Halifax

24 bytes allocated at 0x10a000a10 for linked list element
13 bytes allocated at 0x10a000a30 for name Indianapolis

24 bytes allocated at 0x10a000a40 for linked list element
8 bytes allocated at 0x10a000a60 for name Jamaica

End-of-file found on input.

Printing list element located at 0x10a000890:
roll_num: 10001	name: Angola
roll_num: 10002	name: Bangalore
roll_num: 10003	name: Cairo
roll_num: 10004	name: Dallas
roll_num: 10005	name: Edmonton
roll_num: 10006	name: Fargo
roll_num: 10007	name: Georgia
roll_num: 10008	name: Halifax
roll_num: 10009	name: Indianapolis
roll_num: 10010	name: Jamaica

As you can see, this is considerably different from the output you said you got from this code in message #6 in this thread. But, most importantly the roll_num values shown while walking the linked list match the values found in your input file. I'm not doing anything with atoi(), calloc(), exit(), fclose(), ferror(), fgets(), fopen(), fprintf(), free(), malloc(), printf(), strlen(), or strncpy() that should behave differently on OS X than it should on any Linux distribution. I can't see how you would get the values for roll_num that you showed us in message #6 in this thread from the code you posted in message #8 in this thread.

Last edited by Don Cragun; 02-10-2014 at 08:28 PM.. Reason: Remove duplicated text from cut & paste error.
This User Gave Thanks to Don Cragun For This Post:
# 10  
Old 02-10-2014
Just in case I forgot some lines that may have been modified, here I copy and paste the same code of my post #8 and compile in another PC with same Ubuntu:
Code:
yifangt@box $ gcc -o readf -Wall readfile.c  
yifangt@box $ ./readf 

24 bytes allocated at 0x1797250 for linked list element
7 bytes allocated at 0x1797270 for name Angola

24 bytes allocated at 0x1797290 for linked list element
10 bytes allocated at 0x17972b0 for name Bangalore

24 bytes allocated at 0x17972d0 for linked list element
6 bytes allocated at 0x17972f0 for name Cairo

24 bytes allocated at 0x1797310 for linked list element
7 bytes allocated at 0x1797330 for name Dallas

24 bytes allocated at 0x1797350 for linked list element
9 bytes allocated at 0x1797370 for name Edmonton

24 bytes allocated at 0x1797390 for linked list element
6 bytes allocated at 0x17973b0 for name Fargo

24 bytes allocated at 0x17973d0 for linked list element
8 bytes allocated at 0x17973f0 for name Georgia

24 bytes allocated at 0x1797410 for linked list element
8 bytes allocated at 0x1797430 for name Halifax

24 bytes allocated at 0x1797450 for linked list element
13 bytes allocated at 0x1797470 for name Indianapolis

24 bytes allocated at 0x1797490 for linked list element
8 bytes allocated at 0x17974b0 for name Jamaica

End-of-file found on input.

Printing list element located at 0x1797250:
roll_num: 10001    name: Angola
roll_num: 24736352    name: Bangalore
roll_num: 24736416    name: Cairo
roll_num: 24736480    name: Dallas
roll_num: 24736544    name: Edmonton
roll_num: 24736608    name: Fargo
roll_num: 24736672    name: Georgia
roll_num: 24736736    name: Halifax
roll_num: 24736800    name: Indianapolis
roll_num: 24736864    name: Jamaica

This is almost the same of your output of post #9, that roll_num are wrong except the first one, very similar to post #6 where the first half was not shown. I will try more test. Anyway, gdb is the another one that I am trying to get familiar with at the meantime.
And thank you pointing out that I'm not doing anything with atoi() , calloc() , exit() , fclose() , ferror() , fgets() , fopen() , fprintf() , free() , malloc() , printf() , strlen() , or strncpy() that should behave differently on OS X than it should on any Linux distribution. which I have no experience how they may cause difference.
# 11  
Old 02-10-2014
Now that you have finally shown us the output from the first part of my code, it is obvious that something is overwriting the roll_num member of struct student (after the first element in the linked list) with a pointer. If you convert the bad values in roll_num from decimal to hexadecimal you'll note that the value is between the values of the pointers assigned to temp->name and temp->next.

For example 24736352(decimal) == 1797260(hex) and the pointer assigned to head is 17297250(hex) and the pointer assigned to head->name is 1797270(hex).

This should make absolutely no difference, but please try changing:
Code:
                if(head == NULL)
                        // Create 1st element in the linked list.
                        temp = head = calloc(1, sizeof(struct student));
                else    // Add new element to the end of the linked list.  Note
                        // that the temp->next in the next statement is in the
                        // previous element in the linked list and then temp is
                        // set to a pointer to the (new) current element.
                        temp = temp->next = calloc(1, sizeof(struct student));

to:
Code:
                if(head == NULL) {
                        // Create 1st element in the linked list.
                        head = calloc(1, sizeof(struct student));
                        temp = head;
                } else {// Add new element to the end of the linked list.  Note
                        // that the temp->next in the next statement is in the
                        // previous element in the linked list and then temp is
                        // set to a pointer to the (new) current element.
                        temp->next = calloc(1, sizeof(struct student));
                        temp = temp->next;
                }

Assuming that doesn't make any difference, while you're exploring gdb watch what gets assigned to temp->roll_num.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Solaris

Structure of USCSICMD and CDB for USCSI Read/Write

I am using Solaris 10u11 on x86 machine, i am root, i want to use a gcc compiled code to use read10/write10 function of USCSI solaris library to access data from a normal USB mass storage device. I am able to open a device prior to sending USCSI command via IOCTL. IOCTL command works ok as... (0 Replies)
Discussion started by: danish2012
0 Replies

2. UNIX for Dummies Questions & Answers

Malloc and File Creation

How can I use malloc with copying/creating files? Is this the correct way? I'm a bit confused... int in_fd; int *out_fd; char buffer; in_fd = open(av, O_RDONLY); out_fd = malloc(strlen(av)+strlen(av)+2); sprintf"(buffer,%s/%s", av,av); (5 Replies)
Discussion started by: l flipboi l
5 Replies

3. SCO

Read error on bootinfo structure at 0x800

hi One of our SCO 5.0.6 server is crashing every second or third time during rebooting with kernel panic. According to this SCO manual: http://wdb1.sco.com/kb/showta?taid=106181&qid=1689366546&sid=504668569&pgnum=1 I've saved dump image into a floppy and I've done the following steps: #... (0 Replies)
Discussion started by: ccc
0 Replies

4. Programming

Problem in static structure array in C

Hi, I have a following problem in C. I have a function A in which I used to call another function (function B) and pass an array of values through array variable by using below:- foo=functionB(array); In functionB, i used to just return some "values" (e.g return num;) in order to pass... (1 Reply)
Discussion started by: ahjiefreak
1 Replies

5. Shell Programming and Scripting

problem with listing of directory structure

Hi When im listing (ls -al ) its listing directories without / at the end of directories dir1 dir2 dir3 and i need to list directories with dir1/ dir2/ dir3/ and this should not be made by command ls -F / should be embedded at the last since one of the scripts reads directories... (1 Reply)
Discussion started by: vasanthan
1 Replies

6. Programming

problem in reading file using fread

Hi All, These are the two ways i tried to read file but i getting work with second one not with the first. char buf; // Defining space for buf ctrlfnum = fopen(filename_arr.control_fname,"r"); 1) n = fread(buf,sizeof(buf),1,ctrlfnum); ============== (not works) 2) n =... (4 Replies)
Discussion started by: arunkumar_mca
4 Replies

7. Shell Programming and Scripting

File read & execute problem

Hi folks, Need your help. I am writing a KSH script to read a few commands from a file & execute. I am using the following code to read the file line by line & excute each command. When I am printing each line I see it is printing properly but while excuting, the particular "ps" command... (5 Replies)
Discussion started by: tipsy
5 Replies

8. Programming

How to read task_struct process structure of Linux

Hi, I want to read the task_struct structure in Linux in order to get the names & pids of all processes. How can this be done?? Thanks in adv, molu (4 Replies)
Discussion started by: molu
4 Replies

9. UNIX for Dummies Questions & Answers

Problem w. case structure

Hello, I am having a problem setting a range of numbers for the "case" structure. I can use with no problems, but when I use it doesn't work??? Does the case struture allow numeric ranges? eg: echo -e "enter number between 0 and 60: \c" read $answer case $answer in ) echo... (2 Replies)
Discussion started by: Joe54321
2 Replies

10. Programming

a problem about malloc()

1 . Thanks everyone who read the post. 2 . the programe is that : #include <stdio.h> #include <string.h> void do_it(char *p) { p = (char *) malloc(100); (void )strcpy(p,"1234"); } int main(void) { char *p; do_it(p); (void )printf("p = %s \n",p); (1 Reply)
Discussion started by: chenhao_no1
1 Replies
Login or Register to Ask a Question