Dynamic allocation of a triple indirection

B

Bill Carson

I'm trying to dynamically allocate memory to an array of strings
with the following (incomplete, for reference only) :

int nLines, nChars, m, n, Cols.sTcolumn ;
char ***sAtt;

sAtt = (char ***)malloc(nLines * sizeof(char *));

for(m=0; m < nLines; m++)
{
sAtt[m] = (char **)malloc(Cols.sTcolumn * sizeof(char *));

for(n=0; n < Cols.sTcolumn; n++)
sAtt[m][n] = (char *)malloc(20 * sizeof(char));
};

The reason for building this array is to feed it to sscanf() to parse
lines of text into words :

sscanf(lBuffer, formatdbf, &sAtt[m][0], &sAtt[m][1],
&sAtt[m][2], &sAtt[m][3], &sAtt[m][4]);

The above memory allocation may be wrong, because on output
it prints gibberish. I am not sure if there is a problem with my
memory allocation, or whether I need to add terminating null
characters to my sscanf() output strings. If I feed sscanf()
a predefined 3D array that fits my data, such as:

sAtt[1140][10][20];

then everything works fine.

This is my first foray into dynamic memory allocation and
multiple indirection, so if anyone can see my errors, please
let me know.

Thanks,

Bill
 
C

Case

Bill said:
I'm trying to dynamically allocate memory to an array of strings
with the following (incomplete, for reference only) :

int nLines, nChars, m, n, Cols.sTcolumn ;
char ***sAtt;

sAtt = (char ***)malloc(nLines * sizeof(char *));

for(m=0; m < nLines; m++)
{
sAtt[m] = (char **)malloc(Cols.sTcolumn * sizeof(char *));

for(n=0; n < Cols.sTcolumn; n++)
sAtt[m][n] = (char *)malloc(20 * sizeof(char));
};

The reason for building this array is to feed it to sscanf() to parse
lines of text into words :

sscanf(lBuffer, formatdbf, &sAtt[m][0], &sAtt[m][1],
&sAtt[m][2], &sAtt[m][3], &sAtt[m][4]);

sAtt[m][n] is the address of allocated string size 20; see above
where you do the malloc. So must be sscanf(... sAtt[m][1], ...).
With sAtt[m][n] you retrieve the address of the char* that holds
the address to the actual string. This means you're overwriting
(part of) the sAtt[m] char* array of size Cols.sTcolumn.
The above memory allocation may be wrong, because on output
it prints gibberish. I am not sure if there is a problem with my
memory allocation, or whether I need to add terminating null
characters to my sscanf() output strings. If I feed sscanf()
a predefined 3D array that fits my data, such as:

sAtt[1140][10][20];

Now &sAtt[m][n] yields the same address as sAtt[m][n], because
here sAtt[m][n] refers to an array (instead of a char*).
 
E

Eric Sosman

Bill said:
I'm trying to dynamically allocate memory to an array of strings
with the following (incomplete, for reference only) :

int nLines, nChars, m, n, Cols.sTcolumn ;
char ***sAtt;

sAtt = (char ***)malloc(nLines * sizeof(char *));

The preferred idiom is

sAtt = malloc(nLines * sizeof *sAtt);

.... for reasons that have been discussed many times before.
In this case, the preferred construct corrects an error in
your original -- an error that is harmless on many machines,
but you never know ...
for(m=0; m < nLines; m++)
{
sAtt[m] = (char **)malloc(Cols.sTcolumn * sizeof(char *));

sAtt[m] = malloc(Cols.sTcolumn * sizeof *sAtt[m]);
for(n=0; n < Cols.sTcolumn; n++)
sAtt[m][n] = (char *)malloc(20 * sizeof(char));

sAtt[m][m] = malloc(20 * sizeof *sAtt[m][n]);
};

The reason for building this array is to feed it to sscanf() to parse
lines of text into words :

sscanf(lBuffer, formatdbf, &sAtt[m][0], &sAtt[m][1],
&sAtt[m][2], &sAtt[m][3], &sAtt[m][4]);

sscanf(lBuffer, formatdbf, &sAtt[m][0][0], &sAtt[m][1][0],
&sAtt[m][2][0], &sAtt[m][3][0], &sAtt[m][4][0]);

or more simply

sscanf(lBuffer, formatdbf, sAtt[m][0], sAtt[m][1],
sAtt[m][2], sAtt[m][3], sAtt[m][4]);
The above memory allocation may be wrong, because on output
it prints gibberish. I am not sure if there is a problem with my
memory allocation, or whether I need to add terminating null
characters to my sscanf() output strings. If I feed sscanf()
a predefined 3D array that fits my data, such as:

sAtt[1140][10][20];

then everything works fine.

By pure, dumb luck. The sscanf() arguments are wrong, but
you're getting away with it. I suggest a review of Section 6
of the comp.lang.c Frequently Asked Questions list

http://www.eskimo.com/~scs/C-faq/top.html
 
C

Case

Bill said:
I'm trying to dynamically allocate memory to an array of strings
with the following (incomplete, for reference only) :

int nLines, nChars, m, n, Cols.sTcolumn ;
char ***sAtt;

sAtt = (char ***)malloc(nLines * sizeof(char *));

for(m=0; m < nLines; m++)
{
sAtt[m] = (char **)malloc(Cols.sTcolumn * sizeof(char *));

for(n=0; n < Cols.sTcolumn; n++)
sAtt[m][n] = (char *)malloc(20 * sizeof(char));
};

The reason for building this array is to feed it to sscanf() to parse
lines of text into words :

sscanf(lBuffer, formatdbf, &sAtt[m][0], &sAtt[m][1],
&sAtt[m][2], &sAtt[m][3], &sAtt[m][4]);

sAtt[m][n] is the address of allocated string size 20; see above
where you do the malloc. So must be sscanf(... sAtt[m][1], ...).
With &sAtt[m][n] you retrieve the address of the char* that holds
the address to the actual string. This means you're overwriting
(part of) the sAtt[m] char* array of size Cols.sTcolumn.
The above memory allocation may be wrong, because on output
it prints gibberish. I am not sure if there is a problem with my
memory allocation, or whether I need to add terminating null
characters to my sscanf() output strings. If I feed sscanf()
a predefined 3D array that fits my data, such as:

sAtt[1140][10][20];

Now &sAtt[m][n] yields the same address as sAtt[m][n], because
here sAtt[m][n] refers to an array (instead of a char*).
 
B

Bill Carson

Thanks, I now see the error of my ways. It compiles
and runs as expected thanks to your help.

Bill
 
C

CBFalconer

Bill said:
I'm trying to dynamically allocate memory to an array of strings
with the following (incomplete, for reference only) :

int nLines, nChars, m, n, Cols.sTcolumn ;
char ***sAtt;
.... snip ...

Stop right there. What is sAtt as you have declared it?

**sATT is a pointer to a char (char *)
*sATT is a pointer to a pointer to a char.
sATT is a pointer to a pointer to a pointer to a char.

This has very little resemblence to an array of arrays, linearized
into a single array of char.

Now go and read your C book and/or the faq.
 

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
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top