Thread: Help -- allocating memory in a multidimensional array

  1. #1
    Registered User
    Join Date
    May 2009
    Posts
    5

    Help -- allocating memory in a multidimensional array

    I need some help with allocating memory. This is for a school assignment and the notes I've taken in class aren't quite helping me solve the problem.

    Basically I have a list of words and I make sentences from those words. I've drawn a '-->>' next to the part of the code that is causing a segmentation fault. Please help me understand why.

    I have the following variables:
    Code:
    char **data[4];
    int numOf[] = {0,0,0,0};
    and here is my insane function that is giving me a segmentation fault
    Code:
    void addWord(char *type, char *word)
    {
    	// compare() just returns a 1 if the word matches, or a 0 if not
    	int t = compare(type, "article")?0:compare(type, "noun")?1:compare(type, "verb")?2:3;
    
    	// This method dynamically increases the size of my array. The code is below
    	increaseArray(t);
    	int n = 0;
    	// If there's nothing there ... add something there
    	if (numOf[t] == 0)
    	{
    		data[t][0] = malloc(sizeof(char)*strlen(word));
    		strcpy(data[t][0], word); 
    		numOf[t]++;
    		printLists();
    		return;
    	}
    	// Otherwise add in sorted order
    	else
    	{
    		for (n = 0; n < numOf[t]; n++)
    		{
    			// compareTo() returns a -1 if it's less than, 1 if greater than, or 0 if equal
    			// like in java
    			if (compareTo(word, data[t][n]) < 0)
    			{
    				int i;
    				for (i = 0; i < numOf[t]-n; i++);
    				{
    					// So this is what's breaking ... I allocate memory at the end of my
    					// list equal to the size of the item 1 from the end, then I copy the item
    					// from 1 from the end into the end, rinse and repeat down the list
    					// backwards.  However it breaks on the first attempt to move a word
    -->>					data[t][numOf[t]-i] = malloc(sizeof(char)*strlen(data[t][numOf[t]-i-1]));
    					strcpy(data[t][numOf[t]-i], data[t][numOf[t]-i-1]);
    				}
    				data[t][n] = malloc(sizeof(char)*strlen(word));
    				strcpy(data[t][n], word);
    				numOf[t]++;
    				printLists();
    				return;
    			}
    			// If our word already exists....just ignore it
    			else if (compareTo(word, data[t][n]) == 0) { printLists(); return; }
    		}
    		// If we've gone through the list and not added it by now, then
    		// it is obviously going to go to the end of the list...so let's
    		// allocate memory and put it in!
    		strcpy(data[t][n], word);
    		numOf[t]++;
    		printLists();
    		return;
    	}
    }
    
    // Here is my method for increasing my array dynamically. This may be part of my 
    // problem, and I'm sure there's an easier way.
    void increaseArray(int list)
    {
    	auto char **tempArray[4];
    	tempArray[0] = malloc(numOf[0]);
    	tempArray[1] = malloc(numOf[1]);
    	tempArray[2] = malloc(numOf[2]);
    	tempArray[3] = malloc(numOf[3]);
    
    	int x = 0, y = 0, z = 0;
    	for (x = 0; x < 4; x++)
    	{
    		for (y = 0; y < numOf[x]; y++)
    		{
    			tempArray[x][y] = malloc(sizeof(char)*strlen(data[x][y]));
    			for (z = 0; z < strlen(data[x][y]); z++)
    			{
    				tempArray[x][y][z] = data[x][y][z];
    			}
    		}
    	}
    
    	data[list] = malloc(numOf[list]+1);
    
    	for (x = 0; x < 4; x++)
    	{
    		for (y = 0; y < numOf[x]; y++)
    		{
    			data[x][y] = malloc(sizeof(char)*strlen(tempArray[x][y]));
    			for (z = 0; z < strlen(tempArray[x][y]); z++)
    			{
    				data[x][y][z] = tempArray[x][y][z];
    			}
    		}
    	}
    }

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Code:
    data[t][numOf[t]-i] = malloc(sizeof(char)*strlen(data[t][numOf[t]-i-1]));
    Are you sure this last subscript cannot = -1 the first time?

    Two pieces of advice:
    • when you are trying to work out a syntax problem, don't bother doing it in the the main body of your code. It's too easy to end up with a steadily increasing headache.
    • use a lot of printf(); fflush(stdout); to debug

    The solution to #1 is to set the code aside and try to write as short a program as you can that still encapsulates the issue. That will help to "encapsulate the issue", which is paramount. It will also free you from believing you have something right (or wrong) when you have only done it once. If you encapsulate (refine, focus, whatever) and come up with a few slight variations, this will clarify the syntax/methodology in your mind AND you have a much greater chance than if you just manage to pull it off once in your project, it which case "luck" would be a bad thing.

    Also, by writing abstract examples for yourself (eg, passing a 3D pointer array around) you will build up a collection of easy to consult abstract examples that you wrote.
    Last edited by MK27; 05-20-2009 at 04:41 PM.
    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

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    5
    Ya I put printf() everywhere, I only deleted them all when I posted to the forum, that's how I know exactly where it was breaking.

    And the index should never be -1, because if numOf[t] is 0 it does the above loop, otherwise it comes into this loop, which means numOf[t] >= 1, so it started at numOf[t] - i - 1, which is 1 - 0 - 1 = 0.

    I've worked through all the algorithms a hundred times, I don't know what I'm missing.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    strlen does not include the null terminator in its size count.


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

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    5
    Okay so I added a +1 to the end of all my malloc() calls (inside the parenthesis of course). Still get a Segmentation fault at the same place.

    Also, should I be "free()" ing anything up? I'm not quite sure where I would put that in this case.

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    5
    so I noticed I have this code:
    Code:
    int i;
    for (i = 0; i < numOf[t]-n; i++);
    {
    	printf("i is %i, n is %i, numOf[%i] is %i\n", i, n, t, numOf[t]);
    and on the FIRST iteration, 'i' is 1. Why is that? I set it to 0, so why is it 1??

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    5
    A link to my entire .c file is func.c

  8. #8
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    This is the perfect case for a debugger. If it supports your platform, I recommend Valgrind. It's great. Otherwise find out what debuggers are available (gdb probably runs all sorts of places) and give one a shot. But Valgrind really should be the first choice.

    I will tell you that you should store the return value of fgetc() into an int, not a char. Depending on whether char is unsigned or signed, you'll either never see EOF or a valid character will look like EOF.

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by jonathan.plumb View Post
    so I noticed I have this code:
    Code:
    int i;
    for (i = 0; i < numOf[t]-n; i++);
    {
    	printf("i is %i, n is %i, numOf[%i] is %i\n", i, n, t, numOf[t]);
    and on the FIRST iteration, 'i' is 1. Why is that? I set it to 0, so why is it 1??
    I think you believe your print statement is inside your for loop. It is not.

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    In case you still haven't caught onto what tabstop is saying:
    Code:
    for (i = 0; i < numOf[t]-n; i++);
    {

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

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Yeah, your increaseArray() is way off.

    Conceptually, all you need is
    Code:
    data[list] = malloc( sizeof(char*) * (numOf[list] + 1) );
    That is, having done
    data[0] = malloc( sizeof(char*) );
    you can then do
    data[0][0] = malloc( strlen(s) + 1 ); and then copy your string.

    The second thing you're doing wrong (conceptually) in this function is recopying all the actual strings. You have an array of pointers to strings. You can quickly "copy" a string just by copying the pointer.

    So you should be doing
    - make a new array which is one pointer bigger than last time
    - copy all the existing pointers
    - free the old array of pointers (it's now too small anyway, and you've copied all you need)

    Hint: realloc() does ALL that for you
    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. Copy multidimensional array to single array?
    By seepox in forum C Programming
    Replies: 9
    Last Post: 05-08-2006, 11:19 AM
  2. Help allocating and reallocating memory
    By shnuffy in forum C Programming
    Replies: 1
    Last Post: 03-11-2006, 08:38 PM
  3. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM