LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-24-2005, 08:22 AM   #1
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Rep: Reputation: 15
Angry Help with memory allocation questions


I'm a fairly newbie C programmer, self-taught, and have just started working seriously on a project I've been dabbling with for some years. At the moment I have a vary basic ecosystem simulator that is almost ready to be released as version 0.0.1 but I'm getting some baffling run-time crashes. Looking into this I suspect that there is something in the area pointers that I don't quite get and as the program uses such concepts as function pointers and arrays of structures then there is probably some sort of memory leak, or something. Could someone please help fill me in on how memory allocation works in C. I had read several books on the subject but none go into enough detail. For example, as far as I know the following short program should work fine and it compiles without any problems but when I run it I get a "Segmentation fault". Why? What's wrong with this program?

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

// Set up a coordinate structure
struct Coords
{
 int X;
 int Y;
};

// Set up an array of structures (???)
struct Coords **CoordArray;

int main()
{
 // Initialises the first element of the array
 CoordArray[0] = malloc (sizeof (struct Coords));

 return 0;
}
The main program is a Linux port of a version I wrote several years ago in Dos using a Borland command-line compiler that did work so I know the general idea is correct, but I just cannot get the Linux version to stop crashing. Ideas anyone?
 
Old 04-24-2005, 08:50 AM   #2
shivaligupta
Member
 
Registered: Oct 2004
Posts: 45

Rep: Reputation: 15
The program which i hav written below compiles as well as run successfully. Try to see the difference.

#include <stdio.h>
#include <stdlib.h>

// Set up a coordinate structure
struct Coords
{
int X;
int Y;
};

// Set up an array of structures (???)
struct Coords **CoordArray;

int main()
{
// Initialises the first element of the array
CoordArray = malloc (sizeof (struct Coords)*10);
CoordArray[0] = malloc (sizeof (struct Coords));
return 0;
}

See tht CoordArray is a pointer to pointers of struct Coords type elements so before accessing CoordArray[0] u must allocate memory to it.
 
Old 04-24-2005, 10:01 AM   #3
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
Thanks shivaligupta, that's probably what's been missing from my program. Time for another strip-down and re-design! Next question, the main program uses an array of structures called EntityType. There are three main entity types at present which use function pointers within the structure to handle the same messages differently (OOP-style polymorphism in C! Genius!), grass, rabbits and foxes. Foxes eat Rabbits eat Grass. Of course beacuse of this they can all die and spawn depending on whether they eat a lot or get eaten so I need a sort of dynamic structure array where each element of the array has to be able to create and destroy the structure it's pointing to at at will. The main loop then, when searching through the array and getting the movements of each, will check if the element contains an entity or not, preferbly using something like
Code:
if (EntityArray[i] == NULL) { ... ask for the entitys' next move ... } 
else { ... check the next element} ...
However, expanding on the original code snippet, the following program compiles and runs OK but doesn't work as expected:

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

// Set up a coordinate structure
struct Coords
{
 int X;
 int Y;
};

// Set up an array of structures (!!!)
struct Coords **CoordArray;

int main()
{
  // Sets the size of the array, eventually this should be defined
  // by the user either at runtime or through a config file
  int ArraySize = 10;

  // Initialises the first element of the array
  CoordArray = malloc (sizeof (struct Coords)*10);
  CoordArray[0] = malloc (sizeof (struct Coords));

  CoordArray[0]->X = 4;
  CoordArray[0]->Y = 5:

  printf ("CoordArray[0] = (%i, %i).\n", CoordArray[0]->X,CoordArray[0]->Y);

  free (CoordArray[0])

  if (CoordArray[0]) == NULL)
    printf ("It worked!\n");
  else
    printf ("It didn't work.\n");

  printf ("CoordArray[0] = (%i, %i).\n", CoordArray[0]->X, CoordArray[0]->Y);

  return 0;
}
When I compile and run this I get the following output:

CoordArray[0] = (4, 5).
It didn't work.
CoordArray[0]= (0, 5).

First of all why does the condition (CoordArray[0]) == NULL) not work? And secondly I would expect the line
Code:
printf ("CoordArray[0] = (%i, %i).\n", CoordArray[0]->X, CoordArray[0]->Y);
to give a segmentation error as I'm accessing a pointer after it has been free()d. Why doesn't free() assign the pointer the null value (or more to the point what does free() actually do as all it seems to do is set the first value of the struct to zero, Y is still 5). Also putting the line
Code:
CoordArray[0]) == NULL
after the free() line only gives me the compiler warning message "statement with no effect" and running it makes no difference. In summary (!) how do I ensure that when my program is checking through the array that it doesn't re-use an entity that has already died without using some stupid widget like
Code:
if (EntityArray[i]->IsDead == 1)
?

By the way, thanks a lot for getting back to me so fast, I wasn't expecting a reply so soon
 
Old 04-24-2005, 10:05 AM   #4
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
free():ing a pointer doesn't set it to NULL, but it is often a good a idea to set it to NULL afterwards if the pointer stays in scope.
 
Old 04-24-2005, 10:17 AM   #5
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
I tried that but all I got was a compiler warning message saying "malloc3.c warning: statement with no effect" and the if (CoordArray == NULL) statement still didn't work. Is there another way of setting the value to NULL?
 
Old 04-24-2005, 10:30 AM   #6
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
You set a pointer to NULL like you set any variable to anything.
Code:
my_pointer = NULL;
So, in your program where you have an array of pointers and you want to set the first element of that array to NULL.
Code:
CoordArray[0] = NULL;

Last edited by Hivemind; 04-24-2005 at 10:43 AM.
 
Old 04-24-2005, 10:44 AM   #7
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Made a silly mistake in my previous post, please see the edited version.
 
Old 04-24-2005, 10:53 AM   #8
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
Sorry, "CoordArray[0] = NULL;" doesn't work. All I get is a compiler message saying the code has no effect

Last edited by sleepisforwimps; 04-24-2005 at 10:55 AM.
 
Old 04-24-2005, 11:01 AM   #9
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Paste the exact line, don't retype it, copy-and-paste it from the code.
You're not doing
Code:
CoordArray[0] == NULL;
outside an if-statement, are you?
 
Old 04-24-2005, 11:23 AM   #10
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
The CoordArray Conspiracy: Act I, Scene I.

[recieves e-mail notification - goes to website - reads posting]
sleepisforwimps: (under breath) Yeah, yeah whatever.
[looks at source file]
sleepisforwimps: (reading) CoordArray[0] == NULL;
[turns bright red]
sleepisforwimps: Where did that *#~%^|* second equals sign come from?
[alters source file - compiles - runs]
sleepisforwimps: Oh, it works
[looks at posting again]
sleepisforwimps: (reading) Your not doing CoordArray[0] == NULL; outside an if-statement, are you?
[turns room upside down looking for hidden camera]




To be continued...


Alright, ta. Time for a strip-down and redesign methinks. I'll be back when I get my next "Segmentation fault" error
 
Old 04-24-2005, 11:39 AM   #11
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Yeah, post again if you have further problem! I'm sooo stuck on my own projects right now that I don't mind helping others so they, at least, see some progess in their projects.
 
Old 04-24-2005, 05:28 PM   #12
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
Alright next question. The following code works correctly as expected:

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

// Set up a coordinate structure
struct Coords
{
  int X;
  int Y;
};

// Set up an array of structures
struct Coords **CoordArray;

// Function to allocate memory
void AllocMem (struct Coords *NewCoord);

int main()
{
  // Sets the size of the array, eventually this should be defined
  // by the user either at runtime or through a config file
  int ArraySize = 10;

  // Initialises the array
  CoordArray = malloc (sizeof (struct Coords) * ArraySize);

  // Initialises the first element of the array
  CoordArray[0] = malloc (sizeof (struct Coords));
  //AllocMem (CoordArray[0]);

  if (CoordArray[0] != NULL)
    printf ("It worked!\n");
  else
    printf ("It didn't work.\n");

  return 0;
}

void AllocMem (struct Coords *NewCoord)
{
  NewCoord = malloc (sizeof (struct Coords);
}
This compiles fine and the output is "It worked!" OK, all fine. Now lets do a quick change and switch around some comment markers so that we get the following program:

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

// Set up a coordinate structure
struct Coords
{
  int X;
  int Y;
};

// Set up an array of structures
struct Coords **CoordArray;

// Function to allocate memory
void AllocMem (struct Coords *NewCoord);

int main()
{
  // Sets the size of the array, eventually this should be defined
  // by the user either at runtime or through a config file
  int ArraySize = 10;

  // Initialises the array
  CoordArray = malloc (sizeof (struct Coords) * ArraySize);

  // Initialises the first element of the array
  //CoordArray[0] = malloc (sizeof (struct Coords));
  AllocMem (CoordArray[0]);

  if (CoordArray[0]) != NULL)
    printf ("It worked!\n");
  else
    printf ("It didn't work.\n");

  return 0;
}

void AllocMem (struct Coords *NewCoord)
{
  NewCoord = malloc (sizeof (struct Coords);
}
The only difference here is that the malloc() statement is handled by the AllocMem() function and not in main(). CoordArray[0] is passed as a pointer to the AllocMem() function which performs the malloc() action on it. However, although the program compiles fine the output now becomes "It didn't work." meaning that the malloc() statement somehow doesn't work when handled by a function. The only explanation I can think of to explain this is that there is some problem with the scope of the malloc() function when handled in the AllocMem() function but surely this would not be an issue when pointers are used? If the AllocMem() function is rewritten as:

Code:
void AllocMem (struct Coords *NewCoord)
{
  NewCoord = malloc (sizeof (struct Coords);

  if (NewCoord != NULL)
    printf ("It worked!\n");
  else
    printf ("It didn't work.\n");

}
then the output becomes:

It worked!
It didn't work.

In other words the AllocMem() function first sets the element but once the flow returns to main() then it returns to NULL. Why and how do I get around that?

The reason I'm asking by the way is that I'm trying to code a structure that uses function pointers to allow different instances of the structure to respond differently to the same occurence. The ability to create and destroy an element of a structure array within a function is an important design feature, if I don't find a sensible and clean way around this problem it will make the design of the program quite different.
 
Old 04-24-2005, 05:36 PM   #13
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
I read your post very quickly because I have to go to bed soon, but I found one common error. Consider this program (I know it's meaningless):

Code:
#include <stdio.h>

void set_pointer(int *ptr)
{
   ptr = (int*)4711;
}

int main(void)
{
   int *ptr = NULL;

   set_pointer(ptr);

   if(ptr == NULL)
      printf("NULL!\n");
   else
      printf("Not NULL!\n");

   return 0;
}
If you run that program it will *always* print NULL. Why? Well, the pointer itself is passed by value. If you print the address of the ptr in main() and in set_pointer(), you will see that they are different You can print address with:
Code:
printf("%i\n", &ptr)
You need to re-write your function like this:
Code:
void AllocMem (struct Coords **NewCoord)
{
  (*NewCoord) = malloc (sizeof(struct Coords));

  if ((*NewCoord) != NULL)
    printf ("It worked!\n");
  else
    printf ("It didn't work.\n");

}
And call it like:
Code:
struct Coords *new_coord = NULL;

AllocMem(&new_coord);

Last edited by Hivemind; 04-24-2005 at 05:41 PM.
 
Old 04-24-2005, 05:42 PM   #14
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Sorry, I was too quick posting. I've edited the post, hopefully for the better. Replying so you won't miss my changes.
 
Old 04-25-2005, 02:59 AM   #15
sleepisforwimps
Member
 
Registered: Apr 2005
Location: Susex, England.
Distribution: Slackware 10.1, Devil Linux
Posts: 49

Original Poster
Rep: Reputation: 15
Thanks a lot, I tried your code and it worked great. Of course, it's meant another completely new re-design this design is a LOT cleaner than any of my previous attempts. I have to admit that I don't understand why it works but I can kind of think with it and my program hasn't given me any "Segmentation faults" yet (admittedly it doesn't do a whole lot yet) and there are several other designs issues I was having problems with that I'm starting to think with and can probably find a solution for now. My last few designs were quite ugly as my attempts to emulate the Grand Design (TM) kept getting "Segmentation faults" so I kept putting in more and more hacks in order to make it fit but now it's looking a little closer to the Grand Design (TM) than it's ever been!

In brief, thank you, you've made at least one bedroom coder happy today (and even more allergic to sleep than ever)
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
memory allocation esael Linux - General 7 01-12-2008 12:12 PM
memory allocation gecoool Programming 2 10-24-2005 09:47 AM
Help - memory allocation in C zaichik Programming 3 09-04-2005 10:16 AM
memory allocation docGonzo2000 Linux - General 1 05-16-2003 09:24 PM
memory allocation docGonzo2000 Linux - General 1 05-16-2003 09:22 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:20 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration