?
Solved

memory allocation question

Posted on 2003-03-17
11
Medium Priority
?
265 Views
Last Modified: 2010-04-15
The code to the program is at www.losingfast.com/code.txt
rather long so i posted it there

This is a homework program thats just suppose to take an array of names...of format lastname,firstname,age as input and sorts it by either last first or age determined by a command line input flag.  However...in my program when the number of names gets over 8...i get a seg fault..=/

when i run gdb, it says
Enter name 1:lkdsjfladsfjlksdj,3jkl3jlk4jlk3j4,3
Enter name 2:lkjlksdfjlkdlsflsdfj,jlkjlkjkljlkkl3,3
Enter name 3:klsdfjlkjsdlflsk,jlkdsfjlksdjflkjlskdfj,5
Enter name 4:jsdlkflksdhgsdl,sdjflkjdskljflsdjlkfj,3
Enter name 5:kldfjslkfjksdlg,djlkfjskdgjlsdgklh,3
Enter name 6:jdlskjlfgsdhglklksdghl,343,3
Enter name 7:ldskjfksjdklfjsldflk,3434343j,3
Enter name 8:ksdjglksdhgsdhkg,3jlkjlkjkljlk3,3
Enter name 9:lskdglkdslghsledg,8,7

Program received signal SIGSEGV, Segmentation fault.
0x400c49dd in strcpy () from /lib/libc.so.6


char * allocate( int num){
char * numbers;
numbers = (char *) calloc (num, sizeof(char));

return numbers;

the above is how i'm allocating memory..am i doing this right?
0
Comment
Question by:AZN_Wang3
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
11 Comments
 
LVL 1

Expert Comment

by:umangjoshi
ID: 8151661
pls use the structure

struct member
{
   char fname[20];
   char lname[20];
   int age;
};

then define an array of struct member


--------------
or with same structure, add one more thing
struct member *next;

and use linked list
0
 
LVL 6

Accepted Solution

by:
gj62 earned 300 total points
ID: 8151701
No,

What you have done is allocate just the pointers to the names, not the space to store the names.

Think of it this way - your array is an array of pointers - not strings.

char **names; means a pointer to a pointer (in this case, it will be an array of pointers to pointers).

So you first have to make the array of pointers:

names = (char **)malloc(num*sizeof(char*));

Then you have to make room for each of the strings:

for (i = 0; i < num; ++i)
{
  names[i] = (char *)malloc(MAX*sizeof(char));
}

Because this is homework, I'll let you figure out how to put it into your program.

Just a question - why not use a struct to hold everything?  That's probably not the assignment, but it is a much better way of organizing everything...

NOTE: You use MAX in your program, but it is never defined...
0
 
LVL 6

Expert Comment

by:gj62
ID: 8151719
It is generally considered bad form to have string space in a struct when it can be variable lengths.  I would use the following struct:

struct STUDENT
{
  char *firstName;
  char *lastName;
  int age;
};

and then malloc the string space required for each name after you read it in - that way you really only need to have one variable that has string space long enough to hold the longest name, e.g.

char tempName[100];

but you don't waste any space in your structs...

Also, you can allocate your array of structs dynamically as well, using realloc() and not have to statically declare them....
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 46

Expert Comment

by:Kent Olsen
ID: 8152239
>> char **names; means a pointer to a pointer (in this case, it will be an array of pointers to pointers).

Nahhh.  One too many dereferences.  :)  It's an array of pointers to strings, not unlike names[][].


>> It is generally considered bad form to have string space in a struct when it can be variable lengths.  I would use the following struct:

GJ's correct here.  Unless you're reading fixed-length data from a file or will be writing to one, avoid fixed length strings within structs.  (They may be a convenient starting point, but can cause all kinds of headaches as a program develops.)


typdef struct
{
  char Name[20];
} TStruct1;

typedef struct
{
  char *Name;
} TStruct2;

TStruct1 Struct1;
TStruct2 Struct2;

Struct2.Name = (char *)malloc (strlen ("This String"));
strcpy (Struct2.Name, "This String");
strcpy (Struct1.Name, "This String");

In both structures Name is "This String".  Note that the code to access the Name field is the same in both structs.

strcmp (Struct1.Name, Struct2.Name)

And it's a snap to put "This is a very long string that I want to use for the 'Name' field" into struct2, but impossible with struct1.


Regarding the original question:

char * allocate( int num){
  char * numbers;
  numbers = (char *) calloc (num, sizeof(char));
  return numbers;
}

calloc() is a poor choice of API here.  You really want to allocate a buffer large enough to hold "num" characters so malloc() is a better choice.  If you were requesting a table of structs, or pointers, calloc() would be a better fit.

Both will work.  But malloc() is the better choice here.

Kdo
0
 
LVL 6

Expert Comment

by:gj62
ID: 8152436
Kdo,

Semantically, char **p is a pointer to a pointer.  Dereference it once and you have a char *.  

I agree, it is an array of pointers to strings - but what is a string, but a char *  ?

Be careful though...

char **p is similar but different from char p[][];  

You can't use them interchangeably...

0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 8152535
Sorry Gj -- I wasn't specific enough.  As you said, **names is a pointer to a pointer.  However it is NOT an array of pointers to pointers, but it can be used as an array of pointers to strings.

'not unlike names[][]' was a poor example on my part.

I hate Mondays.  Particularly this one.

Kdo
0
 
LVL 6

Expert Comment

by:gj62
ID: 8152606
Got it - cold, grey and rainy here, just to top off a perfect start to a long week.
0
 

Author Comment

by:AZN_Wang3
ID: 8152628
Thx GJ, i got it to work now
Can you explain a little further what i'm doing wrong?
for the struct part...we didn't learn that yet in our class

for allocating dynamic memorry for 2d arrys... i needed to allocated enough buffer for each array[i] ?
0
 
LVL 6

Expert Comment

by:gj62
ID: 8152648
Got it - cold, grey and rainy here, just to top off a perfect start to a long week.
0
 
LVL 6

Expert Comment

by:gj62
ID: 8152762
OK, no structs.

Yes, you need to allocate space for whatever array[i] is pointing to. Remeber, you are NOT allocating a 2D array - you have single array, that contains pointers.  Those pointers may not point to contiguous memory, like a 2D array.

If you want a 2D array (and it really is not a good idea when working with strings - I'll get to why in a moment), you would declare

char names[20][50];

That would create an array of 20 strings, each string 50 long, and it would be contiguous in memory.

Now, why don't you want to do this?  First, there really isn't any advantage to having it contiguous in memory - at least not for unformatted strings of varying length.  Second, both dimensions are fixed at compile-time.  Third, if you get to sorting, it is much easier to just sort the array of pointers, rather than moving all the strings.

With an array of pointers to strings, you can allocate each string exactly the size it needs to be.  In my example, I allocated all the strings to size MAX, but you could just as easily put the allocation in the loop where the names are input, have the name input into a temporary buffer of a large size, then malloc() only what you need by using strlen() on the temporary buffer once the name was entered.

Remember, in my example first malloc simply allocates space for an array of pointers - that's it.  Each array element can now hold a pointer to somewhere else in memory.  

To create each pointer in the array, you have to use malloc() or some other form of memory allocation.  




0
 
LVL 6

Expert Comment

by:gj62
ID: 8152858
If you do allocate "just enough space" using strlen, remember to increase the size by 1 - you need it for the NULL.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
Suggested Courses
Course of the Month9 days, 20 hours left to enroll

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question