473,411 Members | 2,184 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,411 software developers and data experts.

Access to data into an array causes seg-fault

I had a program that worked perfectly, and that read .wav files. I
changed something so the tags of the wave file, instead of being each
in a different variable, are all in an array, called tag. i also set
macros such as #define bitspersample tag[10] so when in my original
program it was written bitspersample now it acts like its tag[10], and
i also moved things that were in the main function into specific
functions. anyways, the program read the sound data into a multi
dimensionnal array.

now, since i did that change, when i try to access a value from that
multi-dimensional array by doing for example printf("%f",
sound[0][69]); in the main function, it causes a segmentation fault at
this precise line.

i think the multi-dimensionnal array is correctly allocated (the
difference between the old and new program is that the whole allocation
thing is in a function instead of the main function, and that it's
bases on values from that tag array to define its sizes instead of
regular integer variables)

now, i can access to a value of this multidimensional array, inside the
function that fills it, and also in the function that calls that
function and that allocates the array before calling it, but not back
in the main function.

is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?

Nov 15 '05 #1
8 1904
On Sun, 03 Jul 2005 06:52:45 -0700, Michel Rouzic wrote:

....
now, i can access to a value of this multidimensional array, inside the
function that fills it, and also in the function that calls that
function and that allocates the array before calling it, but not back
in the main function.

is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?


There's nothing wrong with that as long as sound is set correctly to point
to the memory allocated in the called funciton.

It sounds like there is a problem with your particualr code but we can't
tell what that might be without seeing it.

Lawrence
Nov 15 '05 #2


Michel Rouzic wrote:

is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?


How are you returning the array to main? Are you passing it as a
parameter to the allocating function? If so, are you passing it as
double **sound or double ***sound?

Nov 15 '05 #3


John Bode wrote:
Michel Rouzic wrote:

is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?


How are you returning the array to main? Are you passing it as a
parameter to the allocating function? If so, are you passing it as
double **sound or double ***sound?


well, in main(), i declare it as double **sound, then call my
allocating function by wav_in(double **sound, ...) and inside that
wav_in function i allocate by doing this :

sound=(double **) malloc (channels * sizeof(double *));
for (ic=0;ic<channels;ic++)
sound[ic]=(double *) malloc (sizeof(double) * samplecount);

then i call a function called in_32(double **sound,...) which fills
that array, and then well the array returns by the same way it came in,
the problem is that back to main() i cant access values of my array

Nov 15 '05 #4


Lawrence Kirby wrote:
On Sun, 03 Jul 2005 06:52:45 -0700, Michel Rouzic wrote:

...
now, i can access to a value of this multidimensional array, inside the
function that fills it, and also in the function that calls that
function and that allocates the array before calling it, but not back
in the main function.

is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?


There's nothing wrong with that as long as sound is set correctly to point
to the memory allocated in the called funciton.

It sounds like there is a problem with your particualr code but we can't
tell what that might be without seeing it.

Lawrence


ok, im not sure if its very appropriate to paste code here, but here it
is anyways (i made it minimalistic to show whats the problem, would'nt
have pasted the whole 16 kB code)

#include <stdio.h>
#include <stdint.h>
#include <math.h>
#define formattag tag[5]
#define channels tag[6]
#define samplespersec tag[7]
#define bitspersample tag[10]
#define datasize tag[12]
#define samplecount tag[13]

void in_32(FILE *wavin, double **sound, uint32_t *tag)
{
uint32_t i, ic;
float temp;

for (i=0;i<samplecount;i++)
for (ic=0;ic<channels;ic++)
{
fread(&temp, sizeof(float), 1, wavin);
sound[ic][i]=(double) temp;
}
}

void wav_in(FILE *wavin, double **sound, uint32_t *tag)
{
uint32_t ic;

samplecount=datasize/(bitspersample/8)/channels;

sound=(double **) malloc (channels * sizeof(double *));
for (ic=0;ic<channels;ic++)
sound[ic]=(double *) malloc (sizeof(double) * samplecount);

in_32(wavin, sound, tag);
fclose(wavin);
}

int main(int argc, char *argv[])
{
FILE *wavin;
wavin=fopen(argv[1], "rb");
if (wavin)
{
uint32_t tag[14];
double **sound;

wav_in(wavin, sound, tag);

printf("%f ", sound[0][69]); //that's where the seg fault happens
return 0;
}
}

Nov 15 '05 #5
Michel Rouzic wrote:
is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?
There's nothing wrong with that as long as sound is set correctly to point
to the memory allocated in the called funciton.

Michel, this is were you went wrong. The 'sound' variable Lawrence Kirby
is refering to is the one declared in the main() function. See below.
void wav_in(FILE *wavin, double **sound, uint32_t *tag)
{
uint32_t ic;

samplecount=datasize/(bitspersample/8)/channels;

sound=(double **) malloc (channels * sizeof(double *));
for (ic=0;ic<channels;ic++)
sound[ic]=(double *) malloc (sizeof(double) * samplecount);

in_32(wavin, sound, tag);
fclose(wavin); <Personal note>: I would rather close a file in the same scope that I
opened it. But, hey, its your call :-) }

int main(int argc, char *argv[])
{
FILE *wavin;
wavin=fopen(argv[1], "rb");
if (wavin)
{
uint32_t tag[14];
double **snd; Renamed 'sound' to 'snd' for ease of explantion.
wav_in(wavin, snd, tag);

printf("%f ", snd[0][69]); //that's where the seg fault happens
return 0;
}
}

The basic idea of passing a pointer to a function is to be able to
manipulate the _contents_ of the address pointed to by the pointer, not
the _pointer_ itself.

Suppose, 'snd' points to address location 1000. When you call the
wav_in() function, the 'sound' parameter is also set to point to address
location 1000. Within the wav_in() func when you allocate space and set
'sound' to point to it, 'snd' still points to 1000! Point to note: C has
only 'call by value' and no 'call by reference', i.e. any changes in
value to a passed variable within a function is not reflected in the
variable in caller's scope. Hope this makes sense. Maybe someone here
who has access to the standard can direct you to the appropriate section
(and direct me as to where I can download a copy of it :-] ).

Anyway, you can pass it as 'double ***sound' and do (*sound)=malloc()
and (*sound)[ic]=malloc().

Or, you can change the code as follows:
double **wav_in(FILE *wavin, uint32_t *tag)
{
double **sound;
/*
* rest of your code (incl. allocations)
*/
return sound;
}

and in main()
double **sound;
sound = wav_in(wavin, tag);
cheers,
forayer
Nov 15 '05 #6
In article <11*********************@f14g2000cwb.googlegroups. com>
Michel Rouzic <Mi********@yahoo.fr> wrote:
ok, im not sure if its very appropriate to paste code here ...
It is; especially something cut down to show just the problem, as
you did! :-)
#include <stdio.h>
#include <stdint.h>
#include <math.h>
[snippage]
void wav_in(FILE *wavin, double **sound, uint32_t *tag)
{
uint32_t ic;

samplecount=datasize/(bitspersample/8)/channels;

sound=(double **) malloc (channels * sizeof(double *));
As someone else already noted, the most significant problem here is
that you pass in a value, which wav_in() copies to its local variable
named "sound"; then you overwrite the passed-in value with a new
value from malloc(); then you return, discarding the overwritten
local variable. The caller's version of the variable named "sound"
is not changed.

Another bug is that you used casts above, and here:
for (ic=0;ic<channels;ic++)
sound[ic]=(double *) malloc (sizeof(double) * samplecount);


You probably put in this cast because without it you got a message
of the form:

warning: assignment makes pointer from integer without cast

(more or less). But inserting the cast merely removes the warning,
without fixing the bug. The actual bug is forgetting to include
<stdlib.h>, which is how you tell the C compiler that malloc() has
"void *" as its return type. Without this, your C compiler would
see malloc() here for the first time and, in effect, think: "oh,
that must be a function that returns an int. I will just pretend
I saw:

int malloc();

before this point." Of course, this is the wrong declaration, and
if it works anyway, it is just by luck.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 15 '05 #7
On Sun, 03 Jul 2005 18:35:12 -0700, Michel Rouzic wrote:


Lawrence Kirby wrote:
On Sun, 03 Jul 2005 06:52:45 -0700, Michel Rouzic wrote:

...
> now, i can access to a value of this multidimensional array, inside the
> function that fills it, and also in the function that calls that
> function and that allocates the array before calling it, but not back
> in the main function.
>
> is it a problem due to declaring such a "double **sound" array in the
> main function and doing the malloc's in another function?
There's nothing wrong with that as long as sound is set correctly to point
to the memory allocated in the called funciton.

It sounds like there is a problem with your particualr code but we can't
tell what that might be without seeing it.

Lawrence


ok, im not sure if its very appropriate to paste code here, but here it
is anyways (i made it minimalistic to show whats the problem, would'nt
have pasted the whole 16 kB code)


Yes, posting minimal code is very appropriate.
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#define formattag tag[5]
#define channels tag[6]
#define samplespersec tag[7]
#define bitspersample tag[10]
#define datasize tag[12]
#define samplecount tag[13]

void in_32(FILE *wavin, double **sound, uint32_t *tag)
{
uint32_t i, ic;
float temp;

for (i=0;i<samplecount;i++)
for (ic=0;ic<channels;ic++)
{
fread(&temp, sizeof(float), 1, wavin);
sound[ic][i]=(double) temp;
}
}
First note what you are doing with sound here. It is a value passed into
the function which is used to access an array. That's fine.
void wav_in(FILE *wavin, double **sound, uint32_t *tag)
{
uint32_t ic;

samplecount=datasize/(bitspersample/8)/channels;

sound=(double **) malloc (channels * sizeof(double *));
for (ic=0;ic<channels;ic++)
sound[ic]=(double *) malloc (sizeof(double) * samplecount);

in_32(wavin, sound, tag);
fclose(wavin);
}
Here wav_in is also defined to take a double ** argument for sound.
However it discards the value passed in and sets the local sound variable
to a new value. C passes arguments "by value" which means that the called
function gets a copy of the value, and the parameter variable within it is
independent of the caller. So any changes you make to sound within wav_in
are not visible outside the function.

There is another problem with the code i.e. calling malloc() without a
valid declaration in scope. You can correct that by including the
appropriate header which is <stdlib.h> in this case. You made the mistake
of casting the return value of malloc(). If you hadn't done this the
compiler would have warned you about the problem.
int main(int argc, char *argv[])
{
FILE *wavin;
wavin=fopen(argv[1], "rb");
if (wavin)
{
uint32_t tag[14];
double **sound;

wav_in(wavin, sound, tag);
These 2 lines can never be correct. You have defined an uninitialised
variable sound and then you pass the value of this uninitialised variable
to wav_in(). Acessing the value of an uninitialised variable is always an
error, although the effects tend to be nastier when the variable is a
pointer. What you need is code that updates the value of sound in main()
from wav_in. The most natural way is using a return value from the
function:

double **sound;

sound = wav_in(wavin, tag);

which you could write simply as

double **sound = wav_in(wavin, tag);

and then in wav_in make sound a simple local variable and return it.

You can also update the value of an object in the caller by passing a
pointer to it:

void wav_in(FILE *wavin, double ***soundret, uint32_t *tag)
{
uint32_t ic;
double **sound;

samplecount=datasize/(bitspersample/8)/channels;

sound = malloc (channels * sizeof *sound);
for (ic=0;ic<channels;ic++)
sound[ic] = malloc (samplecount * sizeof *sound[ic]);

in_32(wavin, sound, tag);
fclose(wavin);

*soundret = sound;
}

This uses a pointer to pointer to pointer to double (double ***) but
there's no need to worry about that, it is simply a type that can point at
a pointer to pointer to double (double **). In the caller you would use:

double **sound;

wav_in(wavin, &sound, tag);
printf("%f ", sound[0][69]); //that's where the seg fault happens


In your original code sound is still uninitialised at this point so
accessing its value as this code does is an error.

Lawrence
Nov 15 '05 #8


Michel Rouzic wrote:
John Bode wrote:
Michel Rouzic wrote:

is it a problem due to declaring such a "double **sound" array in the
main function and doing the malloc's in another function?
How are you returning the array to main? Are you passing it as a
parameter to the allocating function? If so, are you passing it as
double **sound or double ***sound?


well, in main(), i declare it as double **sound, then call my
allocating function by wav_in(double **sound, ...) and inside that
wav_in function i allocate by doing this :

sound=(double **) malloc (channels * sizeof(double *));
for (ic=0;ic<channels;ic++)
sound[ic]=(double *) malloc (sizeof(double) * samplecount);


Here's your problem. Remember that in order to write to a parameter,
you must pass a pointer to that parameter. If you want to assign a
pointer value in your allocating function and have that change
reflected in main(), then you need to pass a pointer to the pointer.

In this specific case, you have a double** that you want to assign, so
you need to pass a pointer to it:

double **sound;
wav_in(&sound, ...);

void wav_in(double ***sound, ...)
{
...
*sound = malloc(sizeof (*sound)[0] * channels);
if (*sound)
{
for (ic=0; ic<channels; ic++)
{
(*sound)[ic] = malloc(sizeof (*sound)[ic][0] *
samplecount);
...
}
in_32(*sound,...);
}

Remember, don't cast the result of malloc(), and I've found it's a good
idea to use sizeof on the *object* you're allocating, rather than a
type. IOW, since we're allocating an array of T, use sizeof on an
array element, rather than sizeof T itself. Since the type of sound is
double ***, then the type of *sound is double **, the type of
(*sound)[0] is double*, and the type of (*sound)[0][0] is double, so

malloc(sizeof (*sound)[0] * N)

will allocate N elements of type double*, and

malloc(sizeof (*sound)[0][0] * N)

will allocate N elements of type double.
then i call a function called in_32(double **sound,...) which fills
that array, and then well the array returns by the same way it came in,
the problem is that back to main() i cant access values of my array


The call to in_32 works because you aren't trying to modify the value
of sound itself, just the array elements that sound points to.

Again, remember that if you want to write to a parameter in a function
and have that change reflected in the calling function, you have to
pass a pointer to that parameter.

Personally, when I write allocator functions, I return the thing being
allocated as the function return value. IOW, I'd write it like this:

double **newSoundArray(...)
{
double **sound;
...
sound = malloc(sizeof sound[0] * channels);
if (sound)
{
for (ic = 0; ic < channels; ic++)
{
sound[ic] = malloc (sizeof sound[ic][0] * samplecount);
...

return sound;
}

int main(void)
{
double **sound;

sound = newSoundArray(...);
...
}

Less dereferencing hell this way.

Nov 15 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Lost Bits | last post by:
Hello there C++ pros.. Well, I have recently redesigned an already existing piece of code that someone else designed - its just a search algorithm they developed, and has to perfomr millions of...
6
by: blueblueblue2005 | last post by:
here is a friend function of Class Array, which has two private data member: int size, int *ptr // Array's public member function to return size int getSize() const { return size; } friend...
3
by: Random Person | last post by:
Does anyone know how to use VBA to relink tables between two MS Access databases? We have two databases, one with VBA code and the other with data tables. The tables are referenced by linked...
7
by: dog | last post by:
I've seen plenty of articles on this topic but none of them have been able to solve my problem. I am working with an Access 97 database on an NT4.0 machine, which has many Access reports. I...
11
by: Grasshopper | last post by:
Hi, I am automating Access reports to PDF using PDF Writer 6.0. I've created a DTS package to run the reports and schedule a job to run this DTS package. If I PC Anywhere into the server on...
2
by: david | last post by:
Well, as a matter of fact I_HAD_MISSED a basic thing or two, anyway, although Ollie's answer makes perfectly sense when dealing with classes, it doesn't seem to me to apply as well if you have to...
7
by: Martin Strojek | last post by:
Hi, I have the following problem with developing some web site. I use Visual Studio 2003 to build a website. I tried Windows 2003 Server and switched now back to Windows XP with PWS but the...
4
by: Mike | last post by:
I encountered this problem for the first time today while trying to add some columns to a query from a linked DBASEIII file. The new columns that I added on the design grid do not show up on the...
2
by: gellis72 | last post by:
I'm working on a program that imports a bunch of data from a folder full of Excel files and compiles it into an Access DB. The Excel files have a varying number of rows and columns that need to be...
2
hyperpau
by: hyperpau | last post by:
Before anything else, I am not a very technical expert when it comes to VBA coding. I learned most of what I know by the excellent Access/VBA forum from bytes.com (formerly thescripts.com). Ergo, I...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.