C: Passing one dimension of a 2D array results in segfault - c

it has been a while since I wrote my last lines of C and I'm having issues getting into the hang of C at this moment. I guess this is probably a stupid mistake I'm making, but after having researched the issue for some time I still couldn't figure it out what I'm doing wrong. So this is how my code looks like:
int read_signal_from_file(const char* path, float* signal, SF_INFO * info) {
SNDFILE *sndFile;
sndFile = sf_open(path, SFM_READ, info);
signal = malloc(info->frames * sizeof(float));
long numFrames = sf_readf_float(sndFile, signal, info->frames);
...
}
and
int main(int argc, char *argv[]) {
float** signals = malloc(NUM_FILES * sizeof(float*));
float avg = 0.0;
SF_INFO tmp_info;
for(int i = 0; i < NUM_FILES; i++) {
read_signal_from_file(INPUT_FILES[i], signals[i], &tmp_info);
for(long j = 0; j < tmp_info.frames; j++) {
printf("Sample no #%ld: %f\n", j, signals[i][j]);
}
}
}
inside of read_signal_from_file(), I have no troubles accessing the allocated memory portion. But as soon as I'm trying to access it from the scope of the main function (e.g. as in the printf() example above, I get corrupted results that look suspiciously like uninitialized memory or overflows. If I try to operate on that data, (e.g. by calling vDSP_meanv(), the application crashes with a segfault.

Firstly, you don't have a 2D array, you have a pointer-to-pointer.
Then, the pointers themselves don't point to anything, they are uninitialized because you don't allocate memory for them - thus your program invokes undefined behavior.
So, either allocate memory for them using malloc() in a for loop, or even better, use a real array:
float (*arr)[COLUMN_SIZE] = malloc(sizeof(*arr) * ROW_SIZE);

You are allocating the array of pointers, but you aren't setting them to anything:
float** signals = malloc(NUM_FILES * sizeof(float*));
Which means that you are passing an uninitialized pointer (signals[i]) here:
read_signal_from_file(INPUT_FILES[i], signals[i], &tmp_info)
Because signals[i] is passed by value, it isn't going to be changed in the function call, so it is still going to be uninitialized after read_signal_from_file returns.
A simple change would be to pass by reference:
int read_signal_from_file(const char* path, float* &signal, SF_INFO * info) { ... }

(As mentioned) You are allocating the signals array of pointers, but you don't assign the pointers in this array. When you allocate signal in read_signal_from_file you do reserve the memory but you're assigning the pointer to the local signal variable. If you want to assign the allocated signal to the signals array in your main function you should pass a pointer to the pointer:
read_signal_from_file(INPUT_FILES[i], &signals[i], &tmp_info);
and change your read_signal_from_file function to accept it:
int read_signal_from_file(const char* path, float ** signal, SF_INFO * info) {
// ...
*signal = malloc(info->frames * sizeof(float));
// ...

You pass float *signal to read_signal_from_file() and reassign signal there but that just changes the local var signal, not signals[i] in main().
Change the signature of read_signal_from_file() to
int read_signal_from_file(const char* path, float** signal, SF_INFO * info)
change your malloc() to
*signal = malloc(info->frames * sizeof(float));
and pass signals+i instead of signals[i]

Related

What is the difference between double pointers and single pointer in C functions

I'm new to the C programming language and beginning to mess around with pointers and allocating memory to objects. I wanted to make a simple program that would read in (x) elements from the user and simply print them out using functions.
This was my inital code at the beginning. The code was reading in the user input properly but it gave the wrong output and crashed when displaying elements within the main function.
int main() {
int *myArr;
int myArrSize;
getInputArr(&myArrSize, &myArr);
for (int i = 0; i < myArrSize; i++) {
printf("Element No.%i: %i\n", i, myArr[i]);
}
free(myArr);
return 0;
}
void getInputArr(int *arrSize, int *arr) {
printf("Please Enter Length of Array: \n");
scanf("%i", arrSize);
arr = (int *) malloc(*arrSize * sizeof(int));
printf("Enter %i Numbers!\n", *arrSize);
for (int i = 0; i < *arrSize; i++) {
scanf("%i", &arr[i]);
}
}
After messing around, I finally got it to work using double pointers but I am unsure how it completely works, could someone explain why the code below behaves as expected?
int main() {
int *myArr;
int myArrSize;
getInputArr(&myArrSize, &myArr);
for (int i = 0; i < myArrSize; i++) {
printf("Element No.%i: %i\n", i, myArr[i]);
}
free(myArr);
return 0;
}
void getInputArr(int *arrSize, int **myArr) {
printf("Please Enter Length of Array: \n");
scanf("%i", arrSize);
*myArr = (int *) malloc(*arrSize * sizeof(int));
printf("Enter %i Numbers!\n", *arrSize);
for (int i = 0; i < *arrSize; i++) {
scanf("%i", &((*myArr)[i]));
}
}
There are several surprising things in your implementation, but in the end they all make sense, and indeed they must be present in order for this implementation to work.
You ultimately want int *myArr in main to simulate an array of int, but in getInputArr you refer to it using a "double pointer" int **myArr. But this makes sense, because any time you want to return something from a function "by reference" like this, you need to use a pointer -- an extra pointer. To return an int by reference, you'd use an int *. But to return an int * by reference, you need an int **. The fact that you (correctly) call getInputArr(&myArrSize, &myArr) in main shows that getInputArr's second argument is going to be an int **.
In getInputArr, when you call scanf, you do not have an & next to the argument you pass to scanf for %d to read into. This is highly unusual, but in this case it's absolutely correct, because arrSize is already a pointer.
You then have *myArr = (int *) malloc(*arrSize * sizeof(int)). This was the first thing I spotted in your initial (nonworking) implemenation that was quite wrong. In getInputArr, myArr is a pointer to the pointer that you want to set. So *myArr is the pointer that you want to set.
Finally, you have the jawbreaker call scanf("%i", &((*myArr)[i]));. This looks pretty ugly, and there are probably simpler ways to write it, but it's correct. Let's break it down. Again, myArr is a pointer to the pointer you want to work with. So *myArr is the pointer you want to work with. So (*myArr)[i] is one element of the simulated array (pointed to by the pointer) that you want to work with. You need explicit parentheses, because if you wrote *myArr[i] this would mean, "take the i'th element pointed to by myArr, interpret it as a pointer, and take the contents." But what you want (and, with the parentheses, you have) is "take myArr, interpret it as a pointer, take the thing that it points to, which is *myArr, and interpret that as a pointer, and finally take the i'th element that it (the second pointer) points to."
You've got multiple levels of pointers confusing you. But what if the dynamically allocated array you're dealing with lives inside a struct? Then we only have to deal with the pointer passing ("reference") semantics on that struct.
Consider the below. See the comments for explanation.
/* Basic stuff. */
#include <stdio.h>
#include <stdlib.h>
/* Here's our struct.
* It contains the size of the array,
* and the pointer to the memory allocated for the array.
*/
typedef struct dyn_int_array {
size_t size;
int * array;
} dyn_int_array_t;
/* Forward declarations for a function which creates and
* returns our dynamic_int_array struct.
*/
dyn_int_array_t * create_dyn_int_array();
/* ... and here's where you see that we don't want to
* pass the struct by value, but rather effectively by
* reference by passing a pointer to it.
*/
void scan_into_dyn_int_array(dyn_int_array_t * da);
int main(void) {
dyn_int_array_t * da = create_dyn_int_array();
/* I never bothered to free up the allocated memory,
* because it's not really critical for demonstration here.
*/
}
The implementations of those functions are below, but aren't really critical to this demonstration, as you've hopefully see the pass by reference use of pointers, without having to directly worry about or get confused by two levels of pointer indirection.
dyn_int_array_t * create_dyn_int_array() {
dyn_int_array_t * result = malloc(sizeof(dyn_int_array_t));
fprintf(stdout, "Input an array size: ");
fscanf(stdin, "%zd", &(result->size));
result->array = malloc(sizeof(int) * result->size);
/* Because "da" is already a pointer to dye_int_array_t
* there's no need to get its address.
*/
scan_into_dyn_int_array(result);
return result;
}
void scan_into_dyn_int_array(dyn_int_array_t * da) {
for (int i = 0; i < da->size; i++) {
/* We do have to pass the address of the current
* element of the array to fscanf.
*/
fscanf(stdin, "%d", &(da->array[i]));
}
}

Using a multidimensional array within a structure [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
I have written the following code:
#include <stdio.h>
#include <stdlib.h>
typedef struct _NeuralNetwork{
int input_rows;
int input_columns;
double **inputs;
}NeuralNetwork;
void main(){
// structure variable
NeuralNetwork *nn;
int count;
int i,j;
nn->input_rows = 2;
nn->input_columns = 3;
// create the array of double pointers using # of rows
nn->inputs = (double **)malloc(nn->input_rows * sizeof(double *));
// each pointer gets an array of double values
for (i=0; i<nn->input_rows; i++){
nn->inputs[i] = (double *)malloc(nn->input_columns * sizeof(double));
}
// assign values
count = 0;
for (i = 0; i < nn->input_rows ; i++)
for (j = 0; j < nn->input_columns; j++)
nn->inputs[i][j] = ++count;
// print those values
for (i = 0; i<nn->input_rows; i++)
for (j = 0; j < nn->input_columns; j++)
printf("%f ", nn->inputs[i][j]);
/* Code for further processing and free the
dynamically allocated memory*/
return;
}
When I compile this everything is okay. But after running it, I get a segmentation fault error:
Segmentation fault (core dumped)
I am not sure, where the mistake is. Can somebody help?
Note: When I use nn as structure variable instead of a structure, then everything is fine. But I want to use it as structure pointer and access the structure members via "->" and not via "." since I plan to pass nn as pointer to another function later.
Thank you in advance :)
The variable nn is a pointer, but that pointer is never initialized. You subsequently read and dereference that pointer using an operation such as nn->input_rows = 2;. This invokes undefined behavior.
In this particular case, nn likely contains some garbage value. By dereferencing that pointer value, you are attempting to read from memory you probably aren't allowed to. This is what causes the crash.
By defining nn as an instance of a struct instead of a pointer, as you said you tried, you avoid this issue. You can still however pass a pointer to other functions by taking the address of this variable and passing that to the function, i.e.:
NeuralNetwork nn;
...
myfunction(&nn)
First, do not use void main(), it's non-standard and would eventually cause problems. The right way is int main() or int main(int argc, char** argv). Remember to return a proper value at the end of the main function, possibly 0. Consult the reference here: main function
Second, if you use NeuralNetwork *nn; you must allocate some space for it in memory. It's a pointer to some memory address, if you don't allocate it who knows where it points. That's why you're getting the segfault. You must allocate memory for it in the following way:
NeuralNetwork *nn = malloc(sizeof(NeuralNetwork));
Then it should work properly.

How to dynamically allocate an array of integers in C

A portion of my C code is shown below.
int data[10]={1,3,6,8,1,7,9,1,1,1};
b=10;
int out[b];
process(data, &b, out);
alpha (out, b);
data and out are int arrays. The function process takes the array data whose length is pointed by b (=10) and performs mathematical operation and then returns an array out whose length is then again returned by b (unknown and hence required to be dynamically allocated). Then the array out is sent with function alpha. Right now the function alpha always sends out[10] since b has been declared as 10 in second line of code. How can I allocate array out dynamically so that it contains only valid data returned after function process.
You need to know the difference between dynamic and static allocations.
There are 3 alternatives:
Static allocation:
You need to know in advance the array length. It must be a number and not a variable:
int out[10];
Array is static and is only locally scoped. So if you do:
function do_something()
{
int out[10];
}
you can't use the out array outside the function. But you can define out
outside and send it like this:
function do_something(int* out)
{
// do things
}
...
{
int out[10];
do_something(out);
}
Automatic allocation
When you do
int b = 100;
int out[b];
(which won't compile on gcc without the -std=c99 or -std=c11 flag), you get an automatic variable, which is very convenient if you don't use out out of scope, but can be a bit dangerous. The resulting array is generated in the Stack, and is destroyed when it goes out of scope (which is why it can get you into trouble if you use it freely). See
https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Variable-Length.html
We suggest you use:
Dynamic allocation
Where the array is generated on the Heap and you are responsible to clean it up when you're done with it. The down side is you need to clean it up yourself. The up side is you can use pass it around and use it anywhere.
int b=100;
int* out = (int*) malloc(b * sizeof(int));
// do things with out
free(out);
VERY IMPORTANT:
Do not change the value of the pointer out. If you do, then you won't free the right amount of memory. A nice thing to do is to copy the pointer, and use the copied address for free:
int b=100;
int* out = (int*) malloc(b * sizeof(int));
int* out_copy = out;
// do things with out. don't touch out_copy
free(out_copy);
int *out;
out=(int *) malloc(sizeof(int) * 10);
This will produce array out of integer type with size 10.
You need out to be a pointer - not an array - and you need to pass a pointer to out to the function, just like you do with b.
Example:
void f(int **a, int *size)
{
*a = malloc(23 * sizeof(**a));
*size = 23;
}
/* ... */
int *p = NULL;
int b = 0;
f(&p, &b);
/* 'p' has been allocated and 'b' has its size. */

Program gives segmentation fault while trying to malloc for a pointer member of structure

I wrote my code which works well on netbeans, but gives me a seg fault on putty. I tried to use the gdb, but it seems helpless in which gives me
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006c1 in init_vector ()
(gdb) back trace
#0 0x00000000004006c1 in init_vector ()
#1 0x0000000000400664 in main ()
Here is my code, hope someone can help me out
typedef struct v_
{
int* data;
int size;
int capacity;
}vector;
int main()
{
// vector of floats
vector *vec;
init_vector(vec);
insert_element_vector(vec, 5);
int ele = access_element_vector(vec, 0);
printf("%d\n", ele);
return 0;
}
void init_vector( vector* v)
{
v->data = malloc(sizeof(int) * INIT_VECTOR_SIZE);
v->size = 0;
v->capacity = INIT_VECTOR_SIZE;
}
void insert_element_vector( vector* v, int element_to_insert)
{
if(v->capacity == v->size)
{
v->data = realloc(v->data, sizeof(int) * v->capacity * 2);
v->capacity *= 2;
}
v->data[v->size] = element_to_insert;
v->size += 1;
}
In your code, in init_vector() function, you're directy accessing the passed pointer like
v->data
and more. In case the passed pointer is NULL or invalid, this will invoke undefined behavior.
In your case, vec being an uninitialized automatic local variable, the content is indeterminate. So, the pointer points to invalid memory, essentially. Trying to access it invokes the UB.
To avoid
Always better to initialize the automatic local variables (here, pointer to NULL) and put a (NULL) check for the incoming pointer.
Pass a memory address to init_vector which is valid.
For the second step, you can pass the address of a scalar variable, like
vector *v;
init_vector(&v);
to get things working.
Another possibility is, use malloc() or similar allocator function to allocate memory to vec in main() before passing that to init_vecor().
In main, you declare a *vec;, and then start using it, but it is never associated with any memory. A segmentation fault is exactly what I would expect.
Declare it as vector vec;, and then pass its address to the calls (&vec), and the problem is resolved.

2D arrays passed through functions in c

I'm having a problem with my program. I need my program to read from a text file, the first consists of the dimensions of the 2d array the rest is the contents of the array. I have coded the readWord function which reads from textfiles and it works but when i do anything on the main function with the array it crashes. Please could you help.
int main()
{
int num_it, cols, rows;
char** myworld;
num_it = readWorld(myworld,&cols, &rows);
myworld[1][2]='x';/*it crashes when i make this statement*/
}
int readWorld(char** world, int* width,int* height)
{
int result=0,i,cols=0,rows=0;
char buff[25];
FILE* file = fopen ("world.txt", "r");
fscanf(file, "%d %d %d\n", width, height, &result);
/*Dynamic allocation*/
world = (char**)malloc(*(height)* sizeof(char*));
for(i=0;i<*height;i++)
{
world[i] = (char*)malloc(*width*sizeof(char));
}
/*store data in array*/
while(fgets(buff, sizeof buff, file) != NULL)
{
if (strlen(buff) >1){
for(cols=0; cols<=(strlen(buff)); ++cols)
{
world[rows][cols] = buff[cols];
}
++rows;
}
}
fclose(file);
return result;
}
You need to allocate the memory for myworld in the actual caller!
What's happening here is that you are passing the pointer by value to the function.
The pointer value is changed by the function but that's not going to adjust the one in the caller.
Two options: use a triple indirection (ie pass a pointer to the the pointer) or allocate in the main sub. I prefer the latter, mainly because you can control the memory deallocation in a more symmetrical manner; even if you fixed this problem your code still has the memory leak.
What you're experiencing is undefined behaviour as you are attempting to access memory your program does not own.
Your myworld variable in main is never initialized and points to junk, so when you try to access it bad things happen. Think about why: you are passing a copy of the variable to readWorld. You correctly allocate memory inside there, and make the copy point to it, but the original pointer (in main) still points to whatever random location it pointed to before.
If you want the memory for it to be allocated inside the readWorld function and made accessible via the myworld variable in main then you must pass a pointer to myworld to readWorld; in other words, you must pass a triple pointer.
Try this:
int readWorld(char*** world, int* width,int* height)
{
char **tempworld = malloc(...);
// do whatever
*world = tempworld;
return result;
}
int main()
{
char **myworld = NULL;
readWorld(&myworld, ...);
return 0;
}

Resources