The following code is not working correctly. I'm getting a segfault when I run the program. I ran my program through gdb and found out that the error is occuring in the fillArrays(int**,int) function.
GDB is displaying the following parameters for fillArrays(int**,int):
fillArrays (arrays=0x0,numArrays=3)
Here is the source code to my program
#include <stdlib.h> /* malloc and free */
#define MULTIPLIER 1
#define SMALL 10
#define BIG 20
void allocateSmallArrays(int **arrays,int numArrays) {
int index,freeIndex;
int outerIndex,innerIndex;
arrays = malloc(numArrays*sizeof(int*));
if(arrays == NULL) {
printf("out of memory\n");
exit(1);
}
for(index = 0;index < numArrays;index++) {
arrays[index] = malloc(SMALL*sizeof(int));
if(arrays[index] == NULL) {
printf("out of memory\n");
exit(1);
}
}
}
void fillArrays(int **arrays,int numArrays) {
int outerIndex,innerIndex;
for(outerIndex = 0;outerIndex < numArrays;outerIndex++) {
for(innerIndex = 0;innerIndex < SMALL;innerIndex++)
arrays[outerIndex][innerIndex] = 0;
}
}
void deallocateSmallArrays(int **arrays,int numArrays) {
int index;
for(index = 0;index < numArrays;index++)
free(arrays[index]);
free(arrays);
}
int main(void) {
int numArrays = (3 * MULTIPLIER);
int **arrays = 0;
allocateSmallArrays(arrays,numArrays);
fillArrays(arrays,numArrays);
deallocateSmallArrays(arrays,numArrays);
arrays = 0;
return 0;
}
I was under the assumption that since arrays was allocated in allocateSmallArrays, that passing it through fillArrays would 0 out the allocated arrays and then deallocate in the last function. How do I go about accomplishing this?
The problem is that allocateSmallArrays changes its own copy of the arrays pointer. So the result of the malloc is lost and after the function is done, in the caller arrays is still 0. You could:
Pass a triple pointer int ***arrays and do to *arrays everything you're doing to arrays
Return the pointer instead of void
A C FAQ deals with this very subject.
Related
The following code works fine without the statement d = *dummy; which is a double pointer dereference. However if this line is present, a segmentation fault occurs. Why so?
The code allocates and initializes memory for data structs dynamically. I was trying to simplify access to the returned pointer-to-pointer.
#include <stdlib.h>
#include <stdio.h>
typedef struct s_dummy {
char dummy_number;
} Dummy;
int mock_read_from_external_source() {
return 4;
}
int load_dummies(Dummy** dummies, int* num_of_dummies) {
*num_of_dummies = mock_read_from_external_source();
*dummies = (Dummy*) calloc(*num_of_dummies, sizeof(Dummy));
if (!dummies) {
return 1; // allocation unsuccessful
}
// Iterate dummies and assign their values...
for (int i = 0; i < *num_of_dummies; i++) {
(*dummies + i)->dummy_number = i;
}
return 0;
}
void main() {
Dummy** dummies;
Dummy* d;
int num_of_dummies = 0;
int *p_num_of_dummies = &num_of_dummies;
int err;
err = load_dummies(dummies, p_num_of_dummies);
// Segmentation fault occurs when dummies is dereferenced
d = *dummies;
if (err) {
exit(err);
}
for (int i = 0; i < num_of_dummies; i++) {
printf("Dummy number: %d\n", (*dummies + i)->dummy_number);
}
}
Thanks in advance.
You are getting the fault because of UB, in part caused by trying to use variable objects without memory. dummies, although created as a Dummies **, has never been provided memory. At the very least, your compiler should have warned you about dummies not being initialized in this call:
err = load_dummies(dummies, p_num_of_dummies);
This is easily addressed by simply initializing the variable when it is created:
Dummy** dummies = {0}; //this initialization eliminates compile time warnings
^^^^^
Then come the run-time errors. The first is called a fatal run-time on my system, which means the OS refused to continue because of a serious problem, in this case an attempt to dereference a null pointer in this line:
dummies = (Dummy) calloc(*num_of_dummies, sizeof(Dummy));
Because you created a Dummy ** called dummies, the first step is to create memory for the pointer to pointers dummies, then create memory for the several instances of dummies[i] that will result. Only then can the members of any of them be written to.
Here is one method illustrating how memory can be created for a Dummies pointer to pointers, ( d ) and several Dummies instances ( d[i] ):
Dummy ** loadDummies(int numPointers, int numDummiesPerPointer)
{
int i;
Dummy **d = {0};
d = malloc(numPointers * sizeof(Dummy *));//Create Dummies **
if(!d) return NULL;
for(i=0;i<numPointers;i++)
{ //Now create Dummies *
d[i] = malloc(numDummiesPerPointer*sizeof(Dummy)); //random size for illustration
if(!d[i]) return NULL;
}
return d;
}
In your main function, which by the way should really be prototyped at a minimum as: int main(void){...}, this version of loadDummies could be called like this:
...
Dummies **dummies = loadDummies(4, 80);
if(!dummies) return -1;//ensure allocation of memory worked before using `dummies`.
...
After using this collection of dummies, be sure to free all of them in the reverse order they were created. Free all instances of dummies[0]-dummies[numPointers-1] first, then free the pointer to pointers, dummies
void freeDummies(Dummy **d, int numPointers)
{
int i;
for(i=0;i<numPointers;i++)
{
if(d[i]) free(d[i]);
}
if(d) free(d);
}
Called like this:
freeDummies(dummies, 4);
dummies was never assigned a value, so de-referencing will attempt to reach some random memory which is almost certainly not going to be part of your program's allocated memory. You should have assigned it to &d.
But you don't even need to do that. Just use &d once when you call the function.
Also, if you return the number of dummies allocated instead of 1/0, you can simplify your code. Something like the below (not tested):
#include <stdio.h>
int mock_read_from_external_source() {
return 10;
}
typedef struct Dummy {
int dummy_number;
} Dummy;
int load_dummies(Dummy** dummies) {
int want, i = 0;
if((want = mock_read_from_external_source()) > 0) {
*dummies = (Dummy*) calloc(want, sizeof(Dummy));
if(*dummies) {
// Iterate dummies and assign their values...
for (i = 0; i < want; i++) {
(*dummies)[i].dummy_number = i;
}
}
}
return i;
}
int main() {
Dummy* d = NULL;
int num_of_dummies = load_dummies(&d); // when &d is de-referenced, changes are reflected in d
if(num_of_dummies > 0) {
for (int i = 0; i < num_of_dummies; i++) {
printf("Dummy number: %d\n", d[i].dummy_number);
}
}
if(d) { // clean up
free(d);
}
return 0;
}
I have this function. As you can see, everything is being done in the function, I'm not allocating in the main and then passing anything to it (I'll only return the pointer to the array once the function is done). The function in itself (with a fixed size for the array) works, but the realloc fails.
struct database *parse() {
int i = 0;
int n = 1;
FILE *dbase = (fopen(PATH, "r"));
if (dbase == NULL) {
fprintf(stderr, ERRORE_APERTURA);
exit(EXIT_FAILURE);
}
struct database *database_array = calloc(20*n, sizeof(struct database));
if (database_array == NULL) {
fprintf(stderr, "Impossibile allocare memoria\n");
exit(EXIT_FAILURE);
}
while (feof(dbase) == 0) {
fscanf(dbase, "%[^:]:%[^:]:\n", database_array[i].user, database_array[i].password);
database_array[i].iswritten = 1;
i++;
if (i > 20*n) {
n++;
struct database *new_database_array = realloc(database_array, sizeof(struct database)*(20*n));
database_array = new_database_array;
}
}
database_array[++i].iswritten = 0;
fclose(dbase);
return database_array;
}
I tried reading other explanations, but I can't understand what's wrong here.
The array I allocated with calloc is initially 20. then, when it's filled, I want it to double in size, so I use n, which will be 2, by 20, so 40.
The frustrating thing is that I tried reallocating an array of struct with a simpler program, and doing THE SAME THING works without any problem:
#include <stdio.h>
#include <stdlib.h>
struct prova {
int a;
int b[10];
};
int main() {
struct prova* array_struct = calloc(10, sizeof(struct prova));
array_struct[0].a = 2;
struct prova* tmp = realloc(array_struct, sizeof(struct prova) * 20);
free(array_struct);
array_struct = tmp;
array_struct[1].b[1] = 3;
printf("a = %d", array_struct[0].a);
printf("b = %d\n", array_struct[1].b[1]);
return 0;
}
What am I not seeing? (Please nevermind the fact that I'm not checking if realloc returns NULL, I'll add that later)
struct database *new_database_array = realloc(database_array, sizeof(struct database)*(20*n));
free(database_array);
You can't both reallocate something and deallocate it. You can do either, but once you've done either, the previous allocation no longer exists, so you can't do the other.
After the first line of code above, the value of database_array should not be used anymore because it may not be valid.
I would love to use this code as a dynamic array. Unfortunately, I cannot figure out why the program does not use the allocated memory. Is there something wrong with the parameters of the AddToArray function, maybe?
It is possible to copy and paste this code directly into the IDE and compile, to take a look at the output. The memory seems to be allocated but not used?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
float x;
float y;
} DATA;
int AddToArray (DATA item,
DATA **the_array,
int *num_elements,
int *num_allocated)
{
if(*num_elements == *num_allocated)
{ // Are more refs required?
// Feel free to change the initial number of refs
// and the rate at which refs are allocated.
if (*num_allocated == 0)
{
*num_allocated = 3; // Start off with 3 refs
}
else
{
*num_allocated *= 2;
}// Double the number of refs allocated
// Make the reallocation transactional by using a temporary variable first
void *_tmp = realloc(*the_array, (*num_allocated * sizeof(DATA)));
// If the reallocation didn't go so well, inform the user and bail out
if (!_tmp)
{
printf("ERROR: Couldn't realloc memory!\n");
return(-1);
}
// Things are looking good so far, so let's set the
*the_array = (DATA*)_tmp;
}
(*the_array)[*num_elements] = item;
*num_elements++;
return *num_elements;
}
int main()
{
DATA *the_array = NULL;
int num_elements = 0; // To keep track of the number of elements used
int num_allocated = 0; // This is essentially how large the array is
// Some data that we can play with
float numbers1[4] = {124.3,23423.4, 23.4, 5.3};
float numbers2[4] = { 42, 33, 15, 74 };
int i;
// Populate!
for (i = 0; i < 4; i++)
{
DATA temp;
temp.x = numbers1[i];
temp.y = numbers2[i];
if (AddToArray(temp, &the_array, &num_elements, &num_allocated) == -1)
return 1; // we'll want to bail out of the program.
}
for (i = 0; i < 4; i++)
{
printf("(x:%f,y:%f)\n", the_array[i].x, the_array[i].y);
}
printf("\n%d allocated, %d used\n", num_allocated, num_elements);
// Deallocate!
free(the_array);
// All done.
return 0;
}
In your code, you need to change
*num_elements++;
to
(*num_elements)++;
because, without the explicit parenthesis, the ++ is having higher precedence over * operator. What you want is to increment the value stored in the address, not the other way around.
Check about operator precedence here.
try
(*num_elements)++;
in function
AddToArray()
The bug in your code is that the pointer is incremented, not the value.
..
(*the_array)[*num_elements] = item;
(*num_elements)++;
..
Is this some kind of programming assignment? The code can be improved in many areas here.
There are lots of good algorithms for this kind of problem that are well written and optimized, I suggest that you some research in that area.
I have a dynamic 2d array inside this struct:
struct mystruct{
int mySize;
int **networkRep;
};
In my code block I use it as follows:
struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
freeMatrix(astruct[i].networkRep, 200);
This is how I declare the 2d array:
int** declareMatrix(int **mymatrix, int rows, int columns)
{
mymatrix = (int**) malloc(rows*sizeof(int*));
if (mymatrix==NULL)
printf("Error allocating memory!\n");
int i,j;
for (i = 0; i < rows; i++)
mymatrix[i] = (int*) malloc(columns*sizeof(int));
for(i=0; i<rows; i++){
for(j=0; j<columns; j++){
mymatrix[i][j] = 0;
}
}
return mymatrix;
}
And this is how I free the 2d array:
void freeMatrix(int **matrix, int rows)
{
int i;
for (i = 0; i < rows; i++){
free(matrix[i]);
}
free(matrix);
matrix = NULL;
}
The strange behvior that I'm seeing is that when I compile and run my program everything looks OK. But when I pipe the stdout to a txt file, I'm getting a seg fault. However, the seg fault doesn't occur if I comment out the loop containing the "freeMatrix" call. What am I doing wrong?
I don't see any problem in free code, except, freeMatrix get called for 100 times whereas your allocation is just 1.
So, either you allocate as below:
for(int i=0; i<100; i++) //Notice looping over 100 elements.
astruct[i].networkRep = declareMatrix(astruct[i].networkRep, 200, 200);
Or, free for only 0th element which you have allocated in your original code.
freeMatrix(astruct[0].networkRep, 200);
On sidenote: Initialize your astruct array.
mystruct astruct[100] = {};
struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
freeMatrix(astruct[i].networkRep, 200);
You allocated one astruct but free 100 of them; that will crash if any of the 99 extra ones isn't NULL, which probably happens when you do your redirection. (Since astruct is on the stack, it will contain whatever was left there.)
Other issues:
You're using numeric literals rather than manifest constants ... define NUMROWS and NUMCOLS and use them consistently.
Get rid of the first parameter to declareMatrix ... you pass a value but never use it.
In freeMatrix,
matrix = NULL;
does nothing. With optimization turned on, the compiler won't even generate any code.
if (mymatrix==NULL)
printf("Error allocating memory!\n");
You should exit(1) upon error, otherwise your program will crash and you may not even see the error message because a) stdout is buffered and b) you're redirecting it to a file. Which is also a reason to write error messages to stderr, not stdout.
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
your not passing the address of the pointer. It just passes the value in the memory to the function which is unncessary.
And your only initializing first variable of struct but while you are trying to free the memory you are unallocating memory which is not yet allocated (astruct[1] and so on till 100 ).
When you use a malloc , it actually allocates a bit more memory than you you specified. extra memory is used to store information such as the size of block, and a link to the next free/used block and sometimes some guard data that helps the system to detect if you write past the end of your allocated block.
If you pass in a different address, it will access memory that contains garbage, and hence its behaviour is undefined (but most frequently will result in a crash)
To index and count an unsigned integer type is enough. size_tis the type of choice for this as it is guaranteed to be larger enough to address/index every byte of memory/array's element on the target machine.
struct mystruct
{
size_t mySize;
int ** networkRep;
};
Always properly initialise variables:
struct myStruct astruct[100] = {0};
Several issues with the allocator:
Give it a chance to returned specific error codes. This typically is done by setting using the function returned value to to so.
Use size_t for counters and indicies and sizes ("rows", "columns")(for why please see above).
Do proper error checking.
Clean up in case an error occurs during work.
do not cast the value returned by malloc(), as in C it's not necessary, not recommended
Use perror() to log error, as it gets the most from the OS about the as possibe.
A possible to do this:
int declareMatrix(int *** pmymatrix, size_t rows, size_t columns)
{
int result = 0; /* Be optimistc. */
assert(NULL != pmatrix);
*pmymatrix = malloc(rows * sizeof(**pmymatrix));
if (NULL == *pmymatrix)
{
perror("malloc() failed");
result = -1;
goto lblExit;
}
{
size_t i, j;
for (i = 0; i < rows; i++)
{
(*pmymatrix)[i] = malloc(columns * sizeof(***pmymatrix));
if (NULL == (*pmymatrix)[i])
{
perror("malloc() failed");
freeMatrix(pmymatrix); /* Clean up. */
result = -1;
goto lblExit;
}
for(i = 0; i < rows; ++i)
{
for(j = 0; j < columns; ++j)
{
(*pmymatrix)[i][j] = 0;
}
}
}
}
lblExit:
return 0;
}
Two issues for the de-allocator:
Mark it's work as done be properly de-initilaising the pointer.
Perform validation of input prior to acting on it.
A possible to do this:
void freeMatrix(int *** pmatrix, size_t rows)
{
if (NULL != pmatrix)
{
if (NULL != *pmatrix)
{
size_t i;
for (i = 0; i < rows; ++i)
{
free((*pmatrix)[i]);
}
}
free(*pmatrix);
*pmatrix = NULL;
}
}
Then use the stuff like this:
struct myStruct astruct[100] = {0};
...
int result = declareMatrix(&astruct[0].networkRep, 200, 200);
if (0 != result)
{
fprintf("declareMatrix() failed.\n");
}
else
{
// Note: Arriving here has only the 1st element of astruct initialised! */
// do stuff...
}
{
size_t i;
for(i = 0; i < 100; ++i)
{
freeMatrix(&astruct[i].networkRep, 200);
}
}
I'm new in C programming (my main area is java) and in java there exists the ArrayList which I can make like
ArrayList<Class> arraylist = new ArrayList<Class>();
where my class Class can have several items, such as int, or string.
In c, I found I cannot do that but need to do something like that, so I did this
typedef struct vectorObject {
int myInt;
char *charPointer;
} vectorObject;
I define a pointer of my structure like this:
vectorObject *listVectorObject;
and using
#define MAX_FILE_SIZE 50000
when I want to allocate the memory of that, I use this:
int i;
listVectorObject = malloc(MAX_FILE_SIZE);
if (listVectorObject == NULL ) {
printf("Out of memory1\n");
exit(1);
}
for (i = 0; i < MAX_FILE_SIZE; i++) {
listVectorObject[i].charPointer= malloc(MAX_FILE_SIZE);
if (listVectorObject[i].charPointer == NULL ) {
printf("Out of memory2\n");
exit(1);
}
}
The problem is I always get a
Out of Memory2
I already tried everything and I cannot find where my mistake is. Could you please help me?
Thanks!!
I don't think you want 50000 vectorObjects each with 50000 bytes char-buffer.
So look at this:
first making a list of 1000 vectorObjects
then for each of those allocating a memory chunk to the char-pointer
.
int i, howmany= 1000;
vectorObject *listVectorObject = malloc(sizeof(vectorObject)*howmany); // list of 1000 vectorObjects
if (listVectorObject == NULL ) {
printf("Out of memory1\n");
exit(1);
}
// one file-size char-pointer for each vector object above
for (i = 0; i<howmany; i++) {
listVectorObject[i].charPointer= malloc(MAX_FILE_SIZE);
if (listVectorObject[i].charPointer == NULL ) {
printf("Out of memory2\n");
exit(1);
}
}