Problem with passing pointer to function in C - c

This is one of those annoying things where you know the answer is easy, but you just can't see it.
The printf statement in AllocIntArray shows that arrayPtr is correctly being assigned a memory location, however when the printf statement in main is run, it shows arrayB is still set to NULL.
Can someone show me what I am doing wrong when passing in arrayB to AllocIntArray?
#include <stdio.h>
#include <stdlib.h>
void AllocIntArray(int *arrayPtr, int numElements);
int main()
{
int *arrayB = NULL;
AllocIntArray(arrayB, 10);
printf("Pointer: %p\n", arrayB);
free(arrayB);
getchar();
return EXIT_SUCCESS;
}
void AllocIntArray(int *arrayPtr, int numElements)
{
arrayPtr = (int *)malloc(sizeof(int) * numElements);
printf("Pointer: %p\n", arrayPtr);
if(arrayPtr == NULL)
{
fprintf(stderr, "\nError allocating memory using malloc");
exit(EXIT_FAILURE);
}
}

Pass the double pointer.
#include <stdio.h>
#include <stdlib.h>
void AllocIntArray(int **arrayPtr, int numElements);
int main()
{
int *arrayB = NULL;
AllocIntArray(&arrayB, 10);
printf("Pointer: %p\n", arrayB);
free(arrayB);
getchar();
return EXIT_SUCCESS;
}
void AllocIntArray(int **arrayPtr, int numElements)
{
*arrayPtr = malloc(sizeof(int) * numElements);
printf("Pointer: %p\n", *arrayPtr);
if(*arrayPtr == NULL)
{
fprintf(stderr, "\nError allocating memory using malloc");
exit(EXIT_FAILURE);
}
}

That's because arrayB is passed to AllocIntArray by value. Either pass it by reference (with a pointer-to-pointer), or better, return it from AllocIntArray:
int *AllocIntArray(int numElements)
{
int *arrayPtr = malloc(sizeof(int) * numElements);
printf("Pointer: %p\n", arrayPtr);
if(arrayPtr == NULL)
{
fprintf(stderr, "\nError allocating memory using malloc");
exit(EXIT_FAILURE);
}
return arrayPtr;
}

You need to brush up a bit on parameter passing to functions.
The pointer you are sending to AllocIntArray is being copied into arrayPtr, The line
arrayPtr = (int *)malloc(sizeof(int) * numElements);
assigns a value into the copy, and not the original variable, and therefore the original variable still points to nowhere.
First solution that comes to mind is to send a pointer to that pointer, but I think you'd best do some general brushing up on the matter of parameter passing before going much further.

arrayPtr is a pointer and the pointer is passed by value to the parameter. AllocIntArray can modify its version of arrayPtr but the changes won't be seen by main().
(Edit: if you're using C++) modifying the signature for AllocIntArray to change the type of arrayPtr to a reference ought to fix your problem.
void AllocIntArray(int *&arrayPtr, int numElements)

The basic problem here is you are passing arrayB to AllocIntArray function as passed by value .In AllocIntArray its allocating memory properly and arrayptr is valid but in main function its not the same memory which you are expecting .
This is the basic C programming concept and you can check bu adding print in both the function .
EX: I am sharing the difference between both problem and success case with below example .
/*Code with passed by value as a parameter*/
#include<stdio.h>
#include<stdlib.h>
void AllocateIntarray(int *arrayptr,int numElements)
{
arrayptr = (int*) malloc(sizeof(int)*numElements);
printf("Inside _func_AllocateIntarray_pointer:%p\n",arrayptr);
if(arrayptr == NULL)
{
printf("ERR_MEM_ALLOCATION_FAILED:\n");
}
}
int main()
{
int *arrayB = NULL;
AllocateIntarray(arrayB,10);
printf("Inside _func_mainPointer:%p\n",arrayB);
free(arrayB);
return 0;
}
/*Output :
Inside _func_AllocateIntarray_pointer:0x55be51f96260
Inside _func_mainPointer:(nil)*/
Code with Passed by reference and using double pointer .
#include<stdio.h>
#include<stdlib.h>
void AllocateIntarray(int **arrayptr,int numElements)
{
*arrayptr = malloc(sizeof(int)*numElements);
printf("Inside _func_AllocateIntarray_pointer:%p\n",*arrayptr);
if(*arrayptr == NULL)
{
printf("ERR_MEM_ALLOCATION_FAILED:\n");
}
}
int main()
{
int *arrayB = NULL;
AllocateIntarray(&arrayB,10);
printf("Inside _func_mainPointer:%p\n",arrayB);
free(arrayB);
return 0;
}
/*Output :
Inside _func_AllocateIntarray_pointer:0x562bacd1f260
Inside _func_mainPointer:0x562bacd1f260*/

Related

Using realloc() to increase size of array when even number is typed (from function)

hi im trying to make my array increase its size with realloc from function when even number is typed, but the compiler is displying Segmentation Fault whatever number I type.Any ideas how can i fix this?
#include <stdio.h>
#include <stdlib.h>
int MakeArray(int n,int *ptr)
{
ptr = (int*) malloc(n*sizeof(int));
if(ptr==NULL)
{
puts("Allocation failed");
}
return *ptr;
}
int ReAllocArray(int n,int *ptr)
{
ptr = (int*) realloc(ptr,n*sizeof(int));
if(ptr==NULL)
{
puts("Reallocation failed");
}
return *ptr;
}
int main() {
int n;
int *ptr=NULL;
puts("Enter size of n");
scanf("%d",&n);
MakeArray(n,ptr);
puts("Entering even number is increasing the size of the array by 1");
for(int i =0;i<n;++i)
{
scanf("%d",&ptr[i]);
if(ptr[i]%2==0)
{
++n;
ReAllocArray(n,ptr);
}
}
puts("Your array is:");
for(int i =0;i<n;i++)
{
printf("%d",ptr[i]);
}
return 0;
}
You need to pass pointer to pointer to int to modify it or/and return the reference to the allocated memory
int *MakeArray(size_t n, int **ptr)
{
if(ptr)
{
*ptr = malloc(n*sizeof(**ptr));
if(!*ptr)
{
puts("Allocation failed");
}
}
return *ptr;
}
Same when you realloc
int *ReAllocArray(size_t n, int **ptr)
{
int *tmp = NULL;
if(ptr)
{
tmp = realloc(*ptr,n * sizeof(**ptr));
if(!tmp)
{
puts("Reallocation failed");
}
else
{
*ptr = tmp;
}
}
return tmp;
}
When you call it you need to pass pointer to pointer:
MakeArray(n,&ptr);
ReAllocArray(n,&ptr);
It would be worth checking what those functions return to know if allocations succeeded.
Also:
Use the correct type for sizes (size_t nor int)
Do not cast the result of malloc/realloc. If it does not compiler you are using the wrong (C++) compiler to compile the C code.
Use objects not types in sizeofs
When realloc use a temporary variable. Otherwise, you may have a memory leak
BTW you do not need the MakeArray function at all as realloc will work fine when you pass NULL pointer (it will simple not copy any data to the allocated memory)

Malloc until sudden Termination without error

I am trying to create a program which reads integers from a file with 103690 pairs of integers while skipping lines starting with # and saves them inside an array. Eventhough it does it successfully, it suddenly stops after a specific line (line 5115).
The file looks like this:
#I must
#be
#skipped
8050 6737
8050 7238
The code is:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct {
int start;
int end;
} path;
int doublesize(path* array,int n){
path* new_array=malloc(n*2*sizeof(path));
if(new_array==NULL){
printf("Error allocating memory\n");
abort();
}
for(int i=0;i<n;i++){
new_array[i]=array[i];
}
free(array);
array=new_array;
n*=2;
return n;
}
int main()
{
int maxsize=10;
int test;
path* array=malloc(maxsize*sizeof(path));
if(array==NULL) {
printf("Error allocating memory\n");
abort();
}
FILE* fd=fopen("Wiki-Vote2.txt","r");
if(fd==NULL) {
printf("Error opening file\n");
abort();
}
char buff[200];
int counter=0;
char c;
while(fgets(buff,200,fd)) {
c=buff[0];
if(c=='#') {
continue;
}
test=sscanf(buff,"%d%d",&array[counter].start,&array[counter].end);
printf("%d\t%d\n",array[counter].start,array[counter].end);
printf("Read %d numbers\n", test);
counter++;
if(counter==maxsize){
maxsize=doublesize(array,maxsize);
}
}
fclose(fd);
free(array);
return 0;
}
I have tried reducing the number of integers which works but when I used gdb I saw that it returned the signal sigsegv(I use windows).Could the memory be insufficient or is it something else?
Function arguments are passed by value. That includes pointers. So when you do array=new_array; inside doublesize you are assigning to a copy of the pointer array pointer from main. The value of array inside main function stays the same.
You can pass a pointer to the pointer to change it's value.
int doublesize(path **array,int n){
...
// first dereference array, then access element number i
new_array[i] = (*array)[i];
}
// free the array where array points to, ie array in main
free(*array);
// assign new value to array
*array = new_array;
n *= 2;
return n;
}
int main()
{
...
// pass array by pointer to let doublesize modify it
maxsize = doublesize(&array, maxsize);
...
}
I think it could be clearer to change the doublesize function to return the new pointer and to take a pointer to int variable that represents maxsize, like so:
path *doublesize(path *array, int *maxsize){
int n = *maxsize;
...
free(array);
// maxsize here points to the variable maxsize in main
// let's write n * 2 to it
*maxsize = n * 2;
// return the new pointer
return new_array;
}
int main()
{
...
// array is updated with the new value
// maxsize is updated with
array = doublesize(array, &maxsize);
...
}
The problem is in your resizing function:
int doublesize(path* array,int n){
...
array=new_array;
The variable array is local to the function, so changes to it aren't reflected in the calling function. As a result, array in main now points to freed memory after this function returns, and attempting to dereference that pointer invokes undefined behavior.
You should change this function to accept a path **:
int doublesize(path **array,int n){
path *new_array=malloc(n*2*sizeof(path));
if(new_array==NULL){
printf("Error allocating memory\n");
abort();
}
for(int i=0;i<n;i++){
new_array[i]=(*array)[i];
}
free(*array);
*array=new_array;
n*=2;
return n;
}
And pass the address of array in main:
maxsize=doublesize(&array,maxsize);
In doublesize() you reassign array, but here it's only a local variable, so after the function returns, array in main() still holds the original now freed pointer. So you should pass a double pointer (and use realloc()) so that your function could look like that:
int doublesize(path** array,int n){
path* new_array=realloc( *array, n*2*sizeof(path));
if(new_array==NULL){
printf("Error allocating memory\n");
abort();
}
*array=new_array;
return n*2;
}
Call the function by
maxsize=doublesize(&array,maxsize);

C: using realloc() in seperate function doesn't change array size

I feel as though this shouldn't be such a hard problem and I've tried everything that I've found on similar questions to no avail, so I thought I'd give it a try to ask myself. My code (simplified) is as follows:
#include <stdio.h>
#include <stdlib.h>
void setArraySize(int** arr) {
int arrSize;
printf("\nEnter array size: ");
scanf("%d", &arrSize);
int* tmp = realloc(*arr, arrSize);
if (tmp == NULL) {
printf("Error");
return;
}
*arr = tmp;
}
void auswahl() {
int* arr = NULL;
setArraySize(&arr);
free(arr);
}
int main() {
auswahl();
return 0;
}
When debugging I noticed that my array only contains the integer -842150451. I am using Microsoft Visual Studios 2019 Community. Additionally, even when trying the most basic and safest functions, I attain the same result. Could the problem then have to do with Visual Studios?
#include <stdio.h>
#include <stdlib.h>
void increase(int** data)
{
int* tmp = realloc(*data, 20);
if (tmp == NULL) {
printf("Error");
return;
}
*data = tmp;
}
int main() {
int* arr = NULL;
increase(&arr);
printf("%d", sizeof(arr));
return 0;
}
Thanks in advance for any help!
I changed your second code a little bit (added printf's), it will help you understand what is happening
#include <stdio.h>
#include <stdlib.h>
void increase(int** data)
{
printf ("in increase|*data|%p|\n", *data);
int* tmp = realloc(*data, 20);
printf ("in increase|*data after realloc|%p|\n", *data);
printf ("in increase|tmp after realloc|%p|\n", tmp);
if (tmp == NULL) {
printf("Error");
return;
}
*data = tmp;
printf ("in increase|*data after assign|%p|\n", *data);
}
int main() {
int* arr = NULL;
printf ("in main|arr|%p|\n", arr);
printf ("in main|arr size|%d|\n", sizeof(arr));
increase(&arr);
printf ("in main|arr after increase|%p|\n", arr);
printf ("in main|arr size after increase|%d|\n", sizeof(arr));
return 0;
}
this will output this :
in main|arr|(nil)|
in main|arr size|8|
in increase|*data|(nil)|
in increase|*data after realloc|(nil)|
in increase|tmp after realloc|0x2441010|
in increase|*data after assign|0x2441010|
in main|arr after increase|0x2441010|
in main|arr size after increase|8|
So basically the size of arr doesn't change because it's not an array, it's a pointer to an int, the size here is 8 because it's a 64bits machine, and memory adresses for 64bits need 8 Bytes to be stored, and this is what sizeof() returns the size in bytes of the type you gave it ( int* arr a pointer to an int )
for the other values you can see that you have effectively allocated memory in the heap at address 0x2441010 so your QUOTE"array"QUOTE (it's not an array), starts at this address and have enough space for 20(BYTES) if you wanted 20 integers you should have used realloc(..., 20* sizeof(int)) because these alloc functions use bytes as their unit.
hope this helps you somehow.

Why does my program produce seg-fault when assigning memory to a double pointer C

Why does this program result in a segmentation fault? I'm trying to have an array of pointers that is dynamically allocated memory so that I can have an array of strings.
I've searched for similar issues like How to pass a double pointer to a function without segmentation fault C language
Please explain why it it seg-faulting
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void mem_alloc(char* p, char** dp);
int entries = 0;
int mem_allocated = 0;
int main() {
char* p = "ksdfahj93qhf9";
char* p1 = "siodfnrieopq";
char* p2 = "erf9ih94gri9g";
char** dp = NULL;
mem_alloc(p, dp);
mem_alloc(p1, dp);
mem_alloc(p2, dp);
for(int i = 0; i < entries; i++) {
printf("%s", dp[i]);
}
}
void mem_alloc(char *p, char** dp) {
if(entries == mem_allocated)
if(mem_allocated == 0)
mem_allocated = 3;
void** temp = realloc(dp, mem_allocated * (sizeof(p)));
if(!temp)
perror("Memory allocation failed!");
dp = (char**) temp;
strcpy(dp[entries++], p);
}
In your mem_alloc function you modify the function parameter dp. This modification is not visible outside of the function. As a result, the dp in main never changes and is still set to NULL.
You need to pass the address of this variable to the function, then in the function you dereference that pointer to change it.
So you function becomes:
void mem_alloc(char *p, char ***dp) {
if(entries == mem_allocated)
if(mem_allocated == 0)
mem_allocated = 3;
char **temp = realloc(*dp, mem_allocated * (sizeof(p)));
if(!temp)
perror("Memory allocation failed!");
*dp = temp;
(*dp)[entries++] = strdup(p); // space also needs to be allocated for the new string
}
And you call it like this:
mem_alloc(p, &dp);
Two errors. First is the one mentioned by dbush.
Second, you are not allocating space for your string before you copy it. You can use strndup() instead of strcpy().

How to convert the type of pointer

I want to convert the type of the pointer 'p'. Begining ,the type of the pointer p is void .After allocating four bytes of memory for it, I cast pointer type into 'int',However ,this doesn't work . maybe the sentence p=(int *)p doesn't work.
Please tell me why and solve the problem.thanks.
The coding:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
void *p;
p=malloc(sizeof(int));
if(p == NULL)
{
perror("fail to malloc");
exit(1);
}
p=(int *)p;
*p=100;
printf("the value is : %d\n",*p);
return 0;
}
You'll have an easier time directly casting the void pointer returned by malloc to an int*
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int *p;
p = malloc(sizeof(int));
if(p == NULL)
{
perror("fail to malloc");
exit(1);
}
*p=100;
printf("the value is : %d\n",*p);
return 0;
}
You can't change a variable's type after you have declared it. For what you are asking, you need to declare a separate int* variable and assign your p variable to it with the type-cast:
int *i = (int *)p;
*i = 100;
printf("the value is : %d\n", *i);
Or, simply declare p as a int* to begin with and then type-cast the pointer returned by malloc(), like #GWW showed.
You cant change a variables type, you can do a type cast but that is only temporary.
what you want would be something like *(int*)p = 100;
printf("the value is : %d\n", *(int*)p);
You can't. But you can create a new pointer to int and point to that position, like:
void *p;
p= malloc...
int *pi;
pi= p;
*pi= 25;

Resources