LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 10-25-2009, 03:32 PM   #1
vasmakk
Member
 
Registered: Jan 2009
Distribution: Debian Lenny, Ubuntu 9.04
Posts: 87

Rep: Reputation: 16
Problem with a C program


Hello!

I understand that this question is probably for another topic or thread but I have this little problem trying to understand memory allocation in C. I want to allocate memory from inside a function A() and use this memory from another function B(). The whole process should be controlled from main...

To help you understand on what I mean, I wrote this simple program. But after a successful compilation It gives me many memory allocation errors when run. And memory segmentation errors if I move the definition struct apoint *p outside the main(). How can I correct this to have a successful run?

Please someone with great experience in C could help me?

Regards
Vas




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

struct apoint {
       int x ,y; };


void allocate (struct apoint *);
void printpnt (struct apoint *);


int main(void) {

struct apoint *p;

	allocate (p);
	printpnt (p);
	free (p);
	return 0;
}


void allocate (struct apoint *pnt) {

	pnt = (struct apoint *) malloc (sizeof (struct apoint));
        pnt->x = 10;
	pnt->y = 35;
}


void printpnt (struct apoint *pnt) {
	printf ("(x , y) = (%d , %d)\n", pnt->x , pnt->y);

}

Last edited by vasmakk; 10-25-2009 at 03:36 PM.
 
Old 10-25-2009, 03:48 PM   #2
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,330

Rep: Reputation: 227Reputation: 227Reputation: 227
tried your code in windows and it crashed, dont know why.
 
Old 10-25-2009, 03:54 PM   #3
vasmakk
Member
 
Registered: Jan 2009
Distribution: Debian Lenny, Ubuntu 9.04
Posts: 87

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by smeezekitty View Post
tried your code in windows and it crashed, dont know why.
this is because of Segment Violation
But I don't know what causes it ...
In linux also crashes ...

Unfortunately all malloc() examples I have seen so far use it inside main(). But the application I write ( a small database) Is very big to fit in main() so I have to split it in functions ... Any Ideas?

Vas
 
Old 10-25-2009, 03:55 PM   #4
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

I'm a huge fan of C ... but frankly, this kind of design cries out for a C++ class (instead of a C struct with a C malloc in a C "initial()" function).

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

/*
 * Global typedefs and definitions
 */
struct apoint 
{
  int x ,y; 
};


/*
 * Function prototypes
 */
void allocate (struct apoint **point_pp);
void init2 (struct apoint *point_p);
void printpnt (struct apoint *point_p);

/*
 * allocate: Allocate space for, and initialize an "apoint" structure
 */
void allocate (struct apoint **point_pp) {
	*point_pp = (struct apoint *) malloc (sizeof (struct apoint));

        *point_pp->x = 10;
	*point_pp->y = 35;
}

/*
 * init2: Assume memory is allocated - just initialize the struct
 */
void init2 (struct apoint *point_p) {
        point->x = 10;
	point->y = 35;
}


/*
 * printpnt: Dump the value of "point"
 */
void printpnt (struct apoint *point_p) {
	printf ("(x , y) = (%d , %d)\n", point_p->x , point_p->y);

}

/*
 * program root
 */
int main(void) {
  struct apoint *point1_p = NULL;
  struct apoint point2;

  allocate (&point1_p);
  printpnt (point1_p);

  init2 (&point2);
  printpnt (&point2);

  return 0;
}

Last edited by paulsm4; 10-25-2009 at 03:56 PM.
 
Old 10-25-2009, 03:55 PM   #5
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,330

Rep: Reputation: 227Reputation: 227Reputation: 227
got it:
Code:
#include <stdio.h>
#include <stdlib.h>

struct apoint {
       int x ,y; };


void allocate (struct apoint **);
void printpnt (struct apoint **);


int main(void) {

struct apoint *p;

	allocate (&p);
	printpnt (&p);
	free (p);
	return 0;
}


void allocate (struct apoint **pnt) {

	(*pnt) = (struct apoint *) malloc (sizeof (struct apoint));
        (*pnt)->x = 10;
	(*pnt)->y = 35;
}


void printpnt (struct apoint **pnt) {
	printf ("(x , y) = (%d , %d)\n", (*pnt)->x , (*pnt)->y);

}
you need a double pointer because its actually a pointer to a pointers
so you get the real thing not a copy of it
 
Old 10-25-2009, 04:05 PM   #6
vasmakk
Member
 
Registered: Jan 2009
Distribution: Debian Lenny, Ubuntu 9.04
Posts: 87

Original Poster
Rep: Reputation: 16
Thank you guys!
I'm very obliged to you

Vas
 
Old 10-25-2009, 04:30 PM   #7
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181
Quote:
Originally Posted by paulsm4 View Post
I'm a huge fan of C ... but frankly, this kind of design cries out for a C++ class
But the problem in the original code just calls out for the C++ feature of pass by reference.

In C you can get the semantic equivalent of pass by reference (using uglier syntax) with the method you showed: Add an extra level of indirection.

But in this example in C, that obscures the function and there was a simpler solution.

The apoint* is conceptually the return value of the allocate function. There are many times in C where it is appropriate to implement a conceptual return value by passing a pointer in rather than passing the value out. But in simple cases like this one, a conceptual return value is best implemented as an actual return value.

Instead of
Code:
void allocate (struct apoint **point_pp);
use
Code:
struct apoint *allocate (void);
then
Code:
struct apoint *allocate (void) {
    struct apoint *result = (struct apoint *) malloc (sizeof (struct apoint));
    result->x = 10;
    result->y = 35;
    return result;
}
Instead of
Code:
  allocate (&point1_p);
use
Code:
  point1_p = allocate();
Quote:
Originally Posted by smeezekitty View Post
got it:
Code:
void printpnt (struct apoint **);
you need a double pointer because its actually a pointer to a pointers
so you get the real thing not a copy of it
No! There is no reason to add the extra level of indirection for printpnt.

The extra level of indirection was needed for allocate() when a value that is effectively an output from allocate() was declared as an input.

If you have a good reason to pass a function output as an input to that function (there are often such good reasons) then the way to deal with that in C is to add a level of indirection.

But the apoint* is just an input to printpnt(). Adding an extra level of indirection there just confuses things.

Last edited by johnsfine; 10-25-2009 at 04:36 PM.
 
Old 10-25-2009, 04:39 PM   #8
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,330

Rep: Reputation: 227Reputation: 227Reputation: 227
Quote:
Originally Posted by johnsfine View Post
But the problem in the original code just calls out for the C++ feature of pass by reference.

In C you can get the semantic equivalent of pass by reference (using uglier syntax) with the method you showed: Add an extra level of indirection.
k
But in this example in C, that obscures the function and there was a simpler solution.

The apoint* is conceptually the return value of the allocate function. There are many times in C where it is appropriate to implement a conceptual return value by passing a pointer in rather than passing the value out. But in simple cases like this one, a conceptual return value is best implemented as an actual return value.

Instead of
Code:
void allocate (struct apoint **point_pp);
use
Code:
struct apoint *allocate (void);
then
Code:
struct apoint *allocate (void) {
    struct apoint *result = (struct apoint *) malloc (sizeof (struct apoint));
    result->x = 10;
    result->y = 35;
    return result;
}
Instead of
Code:
  allocate (&point1_p);
use
Code:
  point1_p = allocate();


No! There is no reason to add the extra level of indirection for printpnt.

The extra level of indirection was needed for allocate() when a value that is effectively an output from allocate() was declared as an input.

If you have a good reason to pass a function output as an input to that function (there are often such good reasons) then the way to deal with that in C is to add a level of indirection.

But the apoint* is just an input to printpnt(). Adding an extra level of indirection there just confuses things.
LOL i think you got me and the OP confused.
 
Old 10-25-2009, 04:43 PM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181
Quote:
Originally Posted by smeezekitty View Post
LOL i think you got me and the OP confused.
No, not this time. I do make such mistakes (focus on the content of a post when I should have paid more attention to who posted it). But this time I did notice who posted it.

I posted a correction to your code mainly to keep the OP from being confused by your suggestion. But maybe you can also learn something here.
 
Old 10-25-2009, 04:46 PM   #10
vasmakk
Member
 
Registered: Jan 2009
Distribution: Debian Lenny, Ubuntu 9.04
Posts: 87

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by smeezekitty View Post
LOL i think you got me and the OP confused.
Hi! not confused, on the contrary ...
I prefer smeezekitty's solution.
the struct apoint* allocate() solution applies in this simple example but not in the application I write, where functions have to return multiple pointer values...

Vas
 
Old 10-25-2009, 04:57 PM   #11
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181Reputation: 1181
Quote:
Originally Posted by vasmakk View Post
I prefer smeezekitty's solution.
the struct apoint* allocate() solution applies in this simple example but not in the application I write, where functions have to return multiple pointer values.
Notice I qualified my comments on Paulsm4's suggestion twice with statements like
Quote:
There are many times in C where it is appropriate to implement a conceptual return value by passing a pointer in rather than passing the value out.
I anticipated that the solution I suggested for this simple case could not replace Paulsm4's suggestion in more complicated cases.

I still think it is better to use straight forward code in the simple case and save the more complicated solutions for more complicated problems. But if you want to practice the complicated solution on a simple problem, that's your choice.

I hope you understand that there is an additional flaw in Smeezkitty's expansion of Paulsm4's solution. If a value is just an input, not one of multiple return values, not even a single return value, adding the extra layer of indirection just adds overhead and confusion.
 
Old 10-25-2009, 08:42 PM   #12
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, vasmakk -

Gentle suggestion - when you hear people babbling subjective nonsense about "straight forward code" and "uglier syntax" - run!

But to go back to your original question:
Quote:
I want to allocate memory from inside a function A() and use this memory from another function B(). The whole process should be controlled from main...

Unfortunately all malloc() examples I have seen so far use it inside main()
The answer to this question (all irrelevant issues of "style" aside) is simply:
Quote:
you need to use a pointer to a pointer (**p)
Q: Do you understand why?

Q: Why does passing "**p" as an argument (my reply) do the same thing as returning "*p" as a "return" value (johnsfine's suggestion)?

Q: What would happen if you wanted to allocate memory for TWO (or three, or more) structs, instead of just one?

I think the main point is to understand "pointer", "address", and "pointer to pointer".

And again, if this were C++ ... then your "struct" would be a "class", your "allocate()" would be a "constructor" ... and we probably wouldn't even be having this conversation

Anyway - I hope this discussion was useful for you.

IMHO .. PSM

Last edited by paulsm4; 10-25-2009 at 08:49 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
a program for the 3x+1 problem rec3g Programming 8 03-30-2008 02:01 PM
program problem megadeth Linux - Software 1 05-24-2005 10:58 PM
su program problem xaos5 Linux - Software 6 03-17-2005 02:02 PM
Problem with C program exvor Programming 27 01-04-2005 12:51 PM
C program problem.. Winter Programming 5 05-08-2002 06:10 PM


All times are GMT -5. The time now is 10:30 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration