Thread: Problem reading struct outside of function

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    101

    Problem reading struct outside of function

    I have a struct that is declared outside main() for the purpose of being accessible by other functions. However, I can't access it from all functions for some reason. Here's the relevant part of the code:

    Code:
    struct FILELIST{
    	char filename[255];
    };
    
    struct	FILELIST *filelist;
    
    void load_file_list(char *filename, FILELIST *filelist){ //this function works as expected
    	
    	FILE *handle;
    	char filename_new[255];
    	unsigned long n=0;
    
    	filelist = (FILELIST*)malloc(sizeof(FILELIST)); //allocate mem for first filename
    	
    	while(1){
    			
    		sprintf(filename_new,"%s%06lu.jpg",filename,n);
    
    		if(handle = fopen(filename_new, "rb")){
    			fclose(handle);
    			filelist = ((FILELIST*)realloc(filelist, sizeof(FILELIST)*(n+1))); //add more memory
    			
    			strcpy(filelist[n].filename,filename_new); //copy new filename to struct
    			printf("Filename is %s\n",filelist[n].filename); //this works OK
    
    		}else{
    			printf("No more files\n");
    			break;
    		}
    		n++;
    	}
    }
    
    void print_filename(void){ //this doesn't work
    	printf("Filename: %s\n",filelist[0].filename);
    }

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Doesn't work how? Doesn't compile? Doesn't print what you expect it to? Crashes? You should try compiling with your warnings on. Oh, and when you use a pointer to access a struct, you need to use the arrow operator -> not the . dot operator.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Quote Originally Posted by quzah View Post
    Doesn't work how? Doesn't compile? Doesn't print what you expect it to? Crashes? You should try compiling with your warnings on. Oh, and when you use a pointer to access a struct, you need to use the arrow operator -> not the . dot operator.
    It compiles without warnings. The problem is I get (null) returned when I try to read from the struct using a different function than the one I used to write to it. And if I try to access an element greater than 0 I get a segmentation fault:

    Code:
    printf("Filename: %s\n",filelist[0].filename);
    Outputs: Filename: (null)

    Trying to access an element over 0 gets a seg fault.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Considering it's not a full program...

    Anyway. Yeah, accessing as if it were an array should work, I'm tired. But what I would advise is to make a small program, that all it does first, is use a global pointer, allocate one structure to it, fill that with a string, and use your print function. If that works, you know that's not your issue. It's probably more an issue with you not actually copying the contents over right.
    Code:
    void filefoo( char *name )
    {
        size_t x = 10;
    
        if( filelist == NULL )
        {
            filelist = malloc( sizeof *filelist );
            strcpy( filelist->name, name );
        }
        else
        {
            ...you should have had some way to keep track of how many records you have...
            ...let's pretend you did, and it's called 'totalfiles', and it's global too...
            FILELIST *t;
            totalfiles++;
            t = realloc( totalfiles * sizeof *filelist );
            if( t )
            {
                strcpy( filelist[ totalfiles - 1 ].name, name );
            }
            else
            {
                ...so sad...
            }
        }
    }
    Som'n like that.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    I tried this, with the same result:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    typedef struct {
    	char filename[255];
    } FILELIST;
    
    FILELIST	*filestruct;
    
    void write_to(FILELIST *filelist){
    	char foo[] = "Hello";
    	filelist = malloc(sizeof(filelist));	
    	strcpy(filelist->filename,foo);
    	printf("Wrote to struct: %s\n",filelist->filename);
    }
    
    void read_from(FILELIST *filelist){
    	printf("Read from struct: %s\n",filelist->filename); //null?
    	printf("Read from struct: %s\n",filelist[0].filename); //null?
    }
    
    int main(int argc, char **argv){
    
    	write_to(filestruct); //prints "Hello"
    	read_from(filestruct); //prints (null)
    
    	return 0;
    }

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    This is allocating the size of a pointer:
    Code:
    filelist = malloc(sizeof(filelist));
    You want this:
    Code:
    filelist = malloc(sizeof(*filelist));
    Or you can do this to be the same effect:
    Code:
    filelist = malloc(sizeof(FILELIST));
    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    gcc -Wall -pedantic *.c
    Join Date
    Jan 2009
    Location
    London
    Posts
    60
    Hi, if your struct is declared as a global variable, why do you need to pass it as parameter to the function load_file_list()?... you can access to it from the functions written on the same file, so make it simple!

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by flexo87 View Post
    Hi, if your struct is declared as a global variable, why do you need to pass it as parameter to the function load_file_list()?... you can access to it from the functions written on the same file, so make it simple!
    Good catch. The malloc is actually lost because you are passing it to the function. If you really need to pass it, you need a pointer to a pointer, and to pass the address of the variable, rather than passing its value.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Quote Originally Posted by flexo87 View Post
    Hi, if your struct is declared as a global variable, why do you need to pass it as parameter to the function load_file_list()?... you can access to it from the functions written on the same file, so make it simple!
    I know -- that was my plan at first, but I am having trouble reading anything from that struct after writing to it. I thought the code above might fix this, but it doesn't.

    Again, I only have the problem when trying to grab data from the struct using a function that doesn't write to it as well.

  10. #10
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Both of these produce the same result (get (null) from struct value when trying to read from it):
    Code:
    filelist = malloc(sizeof(FILELIST));
    filelist = (FILELIST*)malloc(sizeof(FILELIST));
    Perhaps GCC is smart enough to figure this out -- I don't get any errors.

  11. #11
    gcc -Wall -pedantic *.c
    Join Date
    Jan 2009
    Location
    London
    Posts
    60
    >The malloc is actually lost because you are passing it to the function. If you really need to pass it, you need a pointer to a pointer, and to pass the address of the variable, rather than passing its value.

    That's exactly what I meant.

  12. #12
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Ok, I see what you're saying now. If I malloc inside main() it works. However, I need a way of doing this from within the function.

  13. #13
    gcc -Wall -pedantic *.c
    Join Date
    Jan 2009
    Location
    London
    Posts
    60
    Quote Originally Posted by synthetix View Post
    Both of these produce the same result (get (null) from struct value when trying to read from it):
    Code:
    filelist = malloc(sizeof(FILELIST));
    filelist = (FILELIST*)malloc(sizeof(FILELIST));
    Perhaps GCC is smart enough to figure this out -- I don't get any errors.
    If you want to work on a parameter and modify its value, you need to work on its address. filelist is a pointer to your struct, but when you modify this value in the function (malloc), only the function will be able to see the change, while the main will see the old value (the value the pointer had when you called the function). you can:

    1-pass the address of the pointer (of the struct you want to modify) to the function
    2-work directly on the global variable.

    The second is easier and simple, but it depends on the kind of program you are writing.

  14. #14
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Got it. Thanks guys! Here's the solution:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    typedef struct {
    	char filename[255];
    } FILELIST;
    
    FILELIST	*filestruct;
    
    void write_to(FILELIST **filelist){
    	char foo[] = "Hello";
    	*filelist = malloc(sizeof(FILELIST));
    	strcpy((*filelist)->filename,foo);
    	printf("Wrote to struct: %s\n",(*filelist)->filename);
    }
    
    void read_from(FILELIST *filelist){
    	char temp[255];
    	strcpy(temp,filelist->filename);
    	printf("Read from struct: %s\n",temp);
    	printf("Read from struct: %s\n",filelist[0].filename);
    	printf("Read from struct: %s\n",filelist->filename);
    }
    
    int main(int argc, char **argv){
    
    	write_to(&filestruct);
    	read_from(filestruct);
    
    	return 0;
    }

  15. #15
    Registered User
    Join Date
    Jul 2009
    Posts
    6

    Robustness

    1) Your programs will tend to be a bit more robust if you consistently check validity of passed parameters in the called function. If a function is passed a pointer, at least make sure the pointer is not NULL before dereferencing.

    2) Use functions like strncpy, instead of strcpy, to contain the operation within the known destination buffer.

    Once you invoke undefined behavior, it's pretty tough to recover.

    -Jon

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Replies: 1
    Last Post: 12-03-2008, 03:10 AM
  3. Possible Loss of data
    By silicon in forum C Programming
    Replies: 3
    Last Post: 03-24-2004, 12:25 PM
  4. problem returning struct member from function
    By yukster in forum C Programming
    Replies: 6
    Last Post: 08-24-2003, 01:21 PM
  5. half ADT (nested struct) problem...
    By CyC|OpS in forum C Programming
    Replies: 1
    Last Post: 10-26-2002, 08:37 AM