Thread: Realloc Strings Array

  1. #1
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193

    Realloc Strings Array

    A little help with this function?
    I'm calling it like this "j = loadWords("diccionario.txt", palabras);"
    Code:
    int loadWords(char *path, char *palabras){
    	FILE *diccionario;
    	diccionario = fopen(path,"r");
    	int count;
    	char buff[7];
    	char *secbuff;
    	printf("Empezando a cargar dic..");
    	while(feof(diccionario)==0){
    		fgets(buff, 6, diccionario);
    		secbuff = realloc(palabras, (sizeof(buff)*(count+1)));
    		count++;
    	}
    	if(fclose(diccionario)!=0){
    		printf("Error cerrando dic");
    	}
    	palabras = secbuff;
    	printf("Palabras cargadas");
    	return count;
    }
    And I'm getting an error while realloc(), I need to load all the words form a txt

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What error?
    Also, count is uninitialized.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Try using an initial malloc line before the while loop where you call realloc. (I think you have to malloc before you can realloc). Unless, of course, palabras was malloced before you passed it to loadWords (I'll get to that at the end).

    As Elysia points out, count is uninitialized so probably much more than zero to start with, which will be a significant problem. Then I think you want to concatenate buff onto secbuff in the while loop. You can use strlen instead of sizeof in realloc if the words may be different sizes, and error check:
    Code:
    int count=0, int len=1;
    char *secbuff=malloc(1);      // that one byte will be the null terminator
    secbuff[0]='\0'                // otherwise the first strcat will segfault
    if (secbuff==NULL) exit (-1);
    [...]
    while(feof(diccionario)==0){
    	fgets(buff, 6, diccionario);
            len+=strlen(buff);
    	if ((secbuff = realloc(secbuff, len))==NULL) exit (-1); // however you would deal with this
            strcat(secbuff,buff);
    	count++;
    }
    palabras=secbuff;
    Notice that i didn't use palabras in the loop, since you are setting it to point to secbuff afterward anyway. Realize that when you used secbuff=realloc(palabras...), which is fine, that secbuff then points to palabras, so there was no point in the subsequent palabras=secbuff.

    I don't actually know where palabras came from, what could be in it, or if it was already malloced, but I'm assuming "none of the above" since that will get thrown away by doing all this (in the original, and in my corrected variant).

    Some people may tell you it is bad to call realloc with a return pointer that is the same as the one passed, secbuff=realloc(secbuff...). Really, this is only a problem if realloc fails, and if realloc fails your computer is out of memory and probably about to crash, so you might as well just exit (or at least "return -1" out of the function).

    Of course, the list of words in palabras will not have any spaces between them this way! You will have to find a solution to that. Also, if you know how many words there are, or can find out before you call loadWords, you could pass in a 2D char* (a list of strings) and use that. This actually simplifies the memory allocation:
    Code:
    char *palabras[20];          // 20 words max
    int X=loadWords("\folder\there\diccionario",palabras,20)
    
    int loadWords(char *path, char **palabras, int max){
    	FILE *diccionario;
    	diccionario = fopen(path,"r");
    	int count=0;
    	char buff[7];
    	printf("Empezando a cargar dic..");
    	while(feof(diccionario)==0 && count<max){
    		fgets(buff, 6, diccionario);
                    if ((palabras[i]=malloc(strlen(buff)+1))==NULL) exit (-1);
    		strcpy(palabras[i],buff);
    		count++;
    	}
    	if(fclose(diccionario)!=0){
    		printf("Error cerrando dic");
    	}
    	printf("Palabras cargadas");
    	return count;
    }
    Last edited by MK27; 12-09-2008 at 08:40 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Ohh thanks, mm how can I do it in a unfixed list of char arrays?

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I'm not sure what you mean by unfixed list. Perhaps this, which is almost the same (but you can get rid of all your buffers):

    Code:
    char palabras[20][7];          // 20 words max
    int X=loadWords("\folder\there\diccionario",palabras)
    
    int loadWords(char *path, char palabras[20][7]){
    	FILE *diccionario;
    	diccionario = fopen(path,"r");
    	int count=0;
    	printf("Empezando a cargar dic..");
    	while(feof(diccionario)==0){
    		fgets(palabras[i], 6, diccionario);
                    count++;
    	}
    	if(fclose(diccionario)!=0){
    		printf("Error cerrando dic");
    	}
    	printf("Palabras cargadas");
    	return count;
    }
    Here there's no need for malloc at all. However, you cannot vary the list size.

    If you do use malloc in the function, remember that palabras can and should be freed at some point, either:

    free(palabras);

    or

    for (i=0; i<X; i++) free(palabras[i]);

    Remember, X was the return value from loadWords which should be the number of actual allocations.

    If by "unfixed", you meant a list whose number of elements could be set, changed, and/or increased (maybe, palabras[][] or **palabras) as far as I know, you can't do that in C.

    However, I only got this stuff straightened around for myself last week, so I could be wrong

    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    And also, you could use a for loop:

    for (count = 0; feof(diccionario) == 0; count++)

    and, of course: If you want to write a serious program, you should use a temp pointer for realloc, beause otherwise, if realloc fails, you have a memory leak.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You should not use feof as a loop control, either. The faq on the board has an explanation for that.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Brafil View Post
    and, of course: If you want to write a serious program, you should use a temp pointer for realloc, beause otherwise, if realloc fails, you have a memory leak.
    See lottarocks, I told you someone would say this! "a serious program" haha, I like that. In reality, if realloc fails you have a lot more problems than just a "memory leak", no matter what pointer you use.

    Anyway, I agree about the feof loop, you should come up with a different way to read lines from a file.

  9. #9
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Mm.. I've changed the idea of string arrays, now I've used an array of structures, it's more easy to me to use it, just allocate the structure..
    But I'm getting Segmentation failure &#172;&#172;
    Code:
    struct _palabras {
    	char palabra[6];
    };
    
    int loadWords(char *path, struct _palabras *pointer){
    	FILE *diccionario;
    	diccionario = fopen(path,"r");
    	pointer = malloc(sizeof(struct _palabras));
    	int count=1;
    	struct _palabras *secbuff;
    	printf("Empezando a cargar dic..");
    	while(feof(diccionario)==0){
    		fgets(pointer[count].palabra, 6, diccionario);
    		secbuff = realloc(pointer, sizeof(struct _palabras)*count);
    		if(secbuff == NULL) {
    			exit(1);
    		}
    		count++;
    	}
    	if(fclose(diccionario)!=0){
    		printf("Error cerrando dic");
    	}
    	pointer = secbuff;
    	printf("Palabras cargadas");
    	return count;
    }

  10. #10
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    1. check return values before use (fopen, malloc etc could fail)
    2. do not use feof to control loop - read FAQ
    3. at the beginnign you have only one struct allocated, pointer[count] when count == 1 is out of bounds access
    4. if realloc succeded - move your pointer to the new location - if it is failed - free old buffer
    5. declare your path as const char* - you are not changing it in the function
    6. pass your "struct _palabras *pointer" argument by pointer (you need pointer to pointer here) if you want the calling function to see the changes you made to the var
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  11. #11
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    I'm getting this error
    *** glibc detected *** ./keyfunc: free(): invalid next size (normal): 0x0804b078 ***
    About your fourth point, what do you mean with move your pointer to the new location? creating another pointer to point that location and in the end store it? which old buffer are you saying? pointer?

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What vart means in simple terms:
    Code:
    T* p = malloc(...);
    T* temp = realloc(p, ...);
    if (temp)
        p = temp;
    else
        free(p);
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    C/C++ Learner & Lover
    Join Date
    Aug 2008
    Location
    Argentina
    Posts
    193
    Is it possible to use reallocate like 1600 times? Maybe there's my problem

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by lautarox
    Is it possible to use reallocate like 1600 times?
    Yes, but it is terribly inefficient to reallocate character by character. It would be far more efficient to keep track of both size (the number of characters in use) and capacity (the total number of characters allocated), then double the capacity everytime the size needs to exceed the current capacity. With such an approach you only need to reallocate 10 or 11 times instead of 1600 times. When you consider that memory allocation is an expensive operation, this could be a huge improvement in efficiency.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    > Some people may tell you it is bad to call realloc with a return pointer that is the same as the one passed, secbuff=realloc(secbuff...).
    > Really, this is only a problem if realloc fails, and if realloc fails your computer is out of memory and probably about to crash,
    > so you might as well just exit (or at least "return -1" out of the function).
    Really?
    It sure will crash if you trash the pointer, and are then in the position of NOT being able to free the 100MB of memory you just leaked.

    If you leak it because you ran out, then you probably had a lot of it to begin with.

    Do the right thing, free up some memory at the moment of potential failure and save the day.

    *shakes head*
    This seems to be a hard message for you to understand.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 03-19-2009, 10:56 AM
  2. Swapping strings in an array of strings
    By dannyzimbabwe in forum C Programming
    Replies: 3
    Last Post: 03-03-2009, 12:28 PM
  3. Build an array of strings dynamically
    By Nazgulled in forum C Programming
    Replies: 29
    Last Post: 04-07-2007, 09:35 PM
  4. Array of strings in C
    By szill in forum C Programming
    Replies: 10
    Last Post: 02-22-2005, 05:03 PM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM