malloc and pointer hell

F

Fatted

I'm trying to learn how to create arrays dynamically. But its just not
happening. Have a look at code below and point and laugh where
appropriate...
First part of program, I'm using an array of pointers, which seems to go
ok. I want to then take it one step further and dynamically create the
array (pointers to pointers). I try to print out the data again,
retrieve the first 3 values (probably by luck), then maybe a pointer
value, and then a seg fault. Doing something wrong, can't see what...

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

int main(void)
{
int * num[5];
int ** digit;
int ** place;
int i;

printf("before assignments\n");
for(i = 0; i < 5; i++)
{
if((num = malloc(sizeof(int) )) == NULL)
{
perror("num malloc\n");
}
*num = i*3;
printf("%d\n",*num);
}

printf("Relooping through the array of pointers\n");
for(i = 0; i < 5; i++)
{
printf("%d\n",*num);
free(num);
}

printf("before pointer to pointer\n");
if((digit = malloc(sizeof(int *) )) == NULL)
{
perror("digit malloc\n");
}
if((place = malloc(sizeof(int **) )) == NULL)
{
perror("place malloc\n");
}
/* hang on to the location of the start of digit */
place = digit;

for(i = 0; i < 5; i++)
{
if((*digit = malloc(sizeof(int) )) == NULL)
{
perror("*digit malloc\n");
}
**digit = i*5;
printf("%d\n",**digit);
*digit++;
}

printf("loop thru digit again\n");

for(i = 0; i < 5; i++)
{
printf("%d\n",**place);
free(*place);
*place++;
}
/*
for(i = 0; i < 5; i++)
{
printf("%d\n",*place);
free(place);
}
*/

free(place);

return(0);
}
 
P

pete

Fatted said:
if((place = malloc(sizeof(int **) )) == NULL)
{
perror("place malloc\n");
}
/* hang on to the location of the start of digit */
place = digit;

That's called "a leak".

/* BEGIN new.c */

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

#define N_ELEM 5

int main(void)
{
int *num[5];
int **digit;
int **place;
size_t i;

printf("before assignments\n");
for (i = 0; i != N_ELEM; ++i) {
if ((num = malloc(sizeof *num)) == NULL) {
perror("num malloc\n");
}
*num = i * 3;
printf("%d\n", *num);
}
printf("Relooping through the array of pointers\n");
for (i = 0; i != N_ELEM; ++i) {
printf("%d\n", *num);
free(num);
}
printf("before pointer to pointer\n");
if ((digit = malloc(N_ELEM * sizeof *digit)) == NULL) {
perror("digit malloc\n");
}
place = digit;
for (i = 0; i != N_ELEM; ++i) {
if((*digit = malloc(sizeof **digit)) == NULL) {
perror("*digit malloc\n");
}
**digit = i * 5;
printf("%d\n", **digit);
++digit;
}
printf("loop thru digit again\n");
digit = place;
for (i = 0; i != N_ELEM; ++i) {
printf("%d\n", **digit);
free(*digit);
++digit;
}
free(place);
return 0;
}

/* END new.c */
 
Z

Zian Smith

Fatted said:
I'm trying to learn how to create arrays dynamically. But its just not
happening. Have a look at code below and point and laugh where
appropriate...
First part of program, I'm using an array of pointers, which seems to go
ok. I want to then take it one step further and dynamically create the
array (pointers to pointers). I try to print out the data again,
retrieve the first 3 values (probably by luck), then maybe a pointer
value, and then a seg fault. Doing something wrong, can't see what...
int * num[5];
int ** digit;
int ** place;
int i;
printf("loop thru digit again\n");
for(i = 0; i < 5; i++)
{
printf("%d\n",**place);
free(*place);
*place++;
}
<snip>

your code isn't very clear, your question isn't either.. are you
trying to dynamically create one dimensional arrays or two dimensional
arrays, or something else?
 
A

Al Bowers

Fatted said:
I'm trying to learn how to create arrays dynamically. But its just not
happening. Have a look at code below and point and laugh where
appropriate...
First part of program, I'm using an array of pointers, which seems to go
ok. I want to then take it one step further and dynamically create the
array (pointers to pointers). I try to print out the data again,
retrieve the first 3 values (probably by luck), then maybe a pointer
value, and then a seg fault. Doing something wrong, can't see what...

Yes your "digit" allocations took to be wrong.
num is an array of 5 int pointers. You have that correct.
However, with digit, it seems to me that you want to allocate
a 2d array.

See the corrections below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
int * num[5];
int ** digit;
int ** place;
int i;
.........snip........

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

int main(void)
{
int *num[5];
int *narray;
int ** digit;
int *tmp;
int i,j;

for(i = 0; i < 5; i++)
{
if((num = malloc(sizeof(int) )) == NULL)
{
perror("num malloc\n");
exit(EXIT_FAILURE);
}
*num = i*3;
printf("*num[%d] = %d\n",i , *num);
}
puts("Freeing num");
for(i = 0; i < 5; i++)
free(num);
puts("\nAllocating an array of ints");
if((narray = malloc((sizeof *narray)*5)) == NULL)
{
perror("narray allocation failure");
exit(EXIT_FAILURE);
}
for(i = 0; i < 5; i++)
{
narray = i*3;
printf("narray[%d] = %d\n",i,narray);
}
puts("Freed narray with free(narray)");
free(narray);
puts("\nPress enter to continue");
getchar();
puts("\n2d allocations. First row= 5 and col = 1");
if((digit = malloc((sizeof *digit)*5)) == NULL)
{
perror("digit allocation error");
exit(EXIT_FAILURE);
}
for(i = 0; i < 5; i++)
if((digit = malloc(sizeof *digit)) == NULL)
{
for(--i;i >= 0; --i) free(digit);
free(digit);
exit(EXIT_FAILURE);
}
for(i = 0; i < 5; i++)
{
digit[0] = i*3;
printf("digit[%d][0] = %d\n",i,digit[0]);
}
puts("\nEnlarging the 2d array to row = 5 and col = 2\n"
" (preserving the original array)");
for(i = 0;i < 5;i++)
{
tmp = realloc(digit,(sizeof *digit)*2);
if(tmp == NULL)
{
perror("Failure in enlarging 2d");
for(i = 0; i < 5;i++) free(digit);
free(digit);
exit(EXIT_FAILURE);
}
digit = tmp;
}
for(i = 0; i < 5;i++) digit[1] = i*6;
for(i = 0; i < 5;i++)
for(j = 0;j < 2;j++)
printf("digit[%d][%d] = %d\n",i,j,digit[j]);
puts("Freeing the 2d array");
for(i = 0;i < 5; i++) free(digit);
free(digit);
return 0;
}
 
J

John Bode

Fatted said:
I'm trying to learn how to create arrays dynamically. But its just not
happening. Have a look at code below and point and laugh where
appropriate...
First part of program, I'm using an array of pointers, which seems to go
ok. I want to then take it one step further and dynamically create the
array (pointers to pointers). I try to print out the data again,
retrieve the first 3 values (probably by luck), then maybe a pointer
value, and then a seg fault. Doing something wrong, can't see what...

Here's the general way to create 2-d arrays on the fly:

#include <stdlib.h>

#define ROWS 5
#define COLS 7

int main (void)
{
int **arr; /* arr will be a 5x7 array of int */
int i, j;

arr = malloc (sizeof *arr * ROWS); /* type of *arr == int * */
if (!arr)
{
/* handle error */
}
else
{
for (i = 0; i < ROWS; i++)
{
arr = malloc (sizeof *arr * COLS); /* type of
*arr == int */
if (!arr)
{
/* handle error */
}
else
{
for (j = 0; j < COLS; j++)
{
arr[j] = /* whatever initial value you prefer
*/
}
}
}
}

return 0;
}

I didn't mark up your program because I frankly don't understand what
you were trying to do, and don't have enough time to seriously study
it.
 
B

Barry Schwarz

I'm trying to learn how to create arrays dynamically. But its just not
happening. Have a look at code below and point and laugh where
appropriate...
First part of program, I'm using an array of pointers, which seems to go
ok. I want to then take it one step further and dynamically create the
array (pointers to pointers). I try to print out the data again,
retrieve the first 3 values (probably by luck), then maybe a pointer
value, and then a seg fault. Doing something wrong, can't see what...

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

int main(void)
{
int * num[5];
int ** digit;
int ** place;
int i;

printf("before assignments\n");
for(i = 0; i < 5; i++)
{
if((num = malloc(sizeof(int) )) == NULL)
{
perror("num malloc\n");
}
*num = i*3;
printf("%d\n",*num);
}

printf("Relooping through the array of pointers\n");
for(i = 0; i < 5; i++)
{
printf("%d\n",*num);
free(num);
}

printf("before pointer to pointer\n");
if((digit = malloc(sizeof(int *) )) == NULL)


This allocates space for only one pointer.
{
perror("digit malloc\n");
}
if((place = malloc(sizeof(int **) )) == NULL)

This allocates the wrong amount of space. place is an int**. The
thing it points to must be an int*. If sizeof(int*) < sizeof(int**),
you will not have enough room to initialize *place.
{
perror("place malloc\n");
}
/* hang on to the location of the start of digit */
place = digit;

As others have noted, you no longer have access to the memory that was
allocated for place. Consequently you cannot free it.
for(i = 0; i < 5; i++)
{
if((*digit = malloc(sizeof(int) )) == NULL)

The first time through the loop, this stores the address of some
allocated memory in the int* pointed to by digit. You never free this
memory.

On subsequent iterations of the loop, that same int* is set to new
addresses. The memory allocated at the old addresses is never freed.
Once *digit is set to a new value, you have no way of accessing the
old memory or freeing it.
{
perror("*digit malloc\n");
}
**digit = i*5;
printf("%d\n",**digit);
*digit++;

This causes the int* that digit points to to point to the byte
immediately after the int value i*5 that was stored there. Unless and
until you do a *digit-- or equivalent, you cannot dereference *digit
since it points to memory you don't own.
}

printf("loop thru digit again\n");

for(i = 0; i < 5; i++)
{
printf("%d\n",**place);

place points to the int* that was allocated for digit. That int* was
incremented to point to memory you don't own. **place is a
dereference of *digit that I mentioned above and invokes undefined
behavior.
free(*place);

*place does not evaluate to the address of an area allocated by
malloc. This also invokes undefined behavior.
*place++;

If the above free had worked, *place would be indeterminate and this
attempt to evaluate it would also result in undefined behavior.
}
/*
for(i = 0; i < 5; i++)
{
printf("%d\n",*place);
free(place);
}


I'm sorry but you got yourself completely lost here. Under the best
of circumstances, *place only exists when i is 0.
*/

free(place);

return(0);
}



<<Remove the del for email>>
 
P

Peter Shaggy Haywood

Groovy hepcat Barry Schwarz was jivin' on 22 Sep 2004 05:19:29 GMT in
comp.lang.c.
Re: malloc and pointer hell's a cool scene! Dig it!
I'm trying to learn how to create arrays dynamically. But its just not
happening. Have a look at code below and point and laugh where
appropriate...
First part of program, I'm using an array of pointers, which seems to go
ok. I want to then take it one step further and dynamically create the
array (pointers to pointers). I try to print out the data again,
retrieve the first 3 values (probably by luck), then maybe a pointer
value, and then a seg fault. Doing something wrong, can't see what...

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

int main(void)
{
int * num[5];
int ** digit;
int ** place;
int i;

printf("before assignments\n");
for(i = 0; i < 5; i++)
{
if((num = malloc(sizeof(int) )) == NULL)
{
perror("num malloc\n");
}
*num = i*3;
printf("%d\n",*num);
}

printf("Relooping through the array of pointers\n");
for(i = 0; i < 5; i++)
{
printf("%d\n",*num);
free(num);
}

printf("before pointer to pointer\n");
if((digit = malloc(sizeof(int *) )) == NULL)


This allocates space for only one pointer.
{
perror("digit malloc\n");
}
if((place = malloc(sizeof(int **) )) == NULL)

This allocates the wrong amount of space. place is an int**. The
thing it points to must be an int*. If sizeof(int*) < sizeof(int**),
you will not have enough room to initialize *place.
{
perror("place malloc\n");
}
/* hang on to the location of the start of digit */
place = digit;

As others have noted, you no longer have access to the memory that was
allocated for place. Consequently you cannot free it.
for(i = 0; i < 5; i++)
{
if((*digit = malloc(sizeof(int) )) == NULL)

The first time through the loop, this stores the address of some
allocated memory in the int* pointed to by digit. You never free this
memory.

On subsequent iterations of the loop, that same int* is set to new
addresses. The memory allocated at the old addresses is never freed.


Wrong. The value of digit is modified in the loop.
Once *digit is set to a new value, you have no way of accessing the
old memory or freeing it.


This causes the int* that digit points to to point to the byte
immediately after the int value i*5 that was stored there. Unless and

No it doesn't. It causes digit to be modified, and also dereferences
the value of digit before the modification, discarding the result. It
does not modify *digit.
until you do a *digit-- or equivalent, you cannot dereference *digit
since it points to memory you don't own.

Actually, it is the value of digit itself that is now invalid.
Dereferencing digit is a no-no.
place points to the int* that was allocated for digit. That int* was
incremented to point to memory you don't own. **place is a

No it wasn't.
dereference of *digit that I mentioned above and invokes undefined
behavior.

Nonsense.
*place does not evaluate to the address of an area allocated by
malloc. This also invokes undefined behavior.

Yes it does.
If the above free had worked, *place would be indeterminate and this
attempt to evaluate it would also result in undefined behavior.

That's right. place is dereferenced, the resulting value is
discarded, and place is incremented. This will result in disaster when
attempting to free the memory at which place used to point.
}
/*
for(i = 0; i < 5; i++)
{
printf("%d\n",*place);
free(place);
}


I'm sorry but you got yourself completely lost here. Under the best
of circumstances, *place only exists when i is 0.


True.

And here we have undefined behaviour. See above.

Fatted, return is not a function. The parentheses around the return
value are superfluous. It's not an error, just unnecessary.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
EmeliaBryc

Latest Threads

Top