This question already has answers here:
How can I create a dynamically sized array of structs?
(10 answers)
Closed 4 years ago.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define LENGHT 20
typedef struct {
unsigned id;
char name[LENGHT];
char genre[LENGHT];
char nazionality [LENGHT];
int year_carrier_started;
bool check;
}Artist;
void print(Artist *arr, int *i);
void addOne(Artist *arr, int *i);
int main(void) {
int index = 5;
Artist *array = malloc(sizeof(int)*index);
for (int i=0;i<index;i++)
{
printf("Insert a number:\n");
scanf("%d",&array[i].id);
}
do
{
addOne(array,&index);
print(array,&index);
}while(1);
system("pause");
free(array);
return EXIT_SUCCESS;
}
void addOne(Artist *arr, int *i)
{
realloc(arr,sizeof(Artist)*(*i)+1);
printf("Insert another one:\n");
scanf("%d",&arr[*i].id);
*i = *i +1;
print(arr,i);
}
void print(Artist *arr, int *i)
{
for (int j=0;j<*i;j++)
{
printf("Number: %d position %d\n",arr[j].id,j);
}
}
Hi guys, I got this struct from a piece of my program, what I need to is to realloc everytime the user wants to add a new Artist. After adding like 10/15 more users, it crashes for no reason (at least for me there is not). What am I doing wrong? (Dat *i is passed by reference, it counts how many artists are there already).
How to properly use realloc in c(?)
After adding like 10/15 more users, it crashes for no reason
#Christian Gibbons well advises: use the return value of realloc(). The former value of array may not be valid.
Multiply the right values
// sizeof(Artist)*(*i)+1
sizeof(Artist)*((*i)+1)
Use the return value of realloc()
// realloc(array,sizeof(Artist)*(*i)+1);
void *new_ptr = realloc(array,....
Check realloc() results
// realloc(array,sizeof(Artist)*(*i)+1);
void *new_ptr = realloc(array,....
if (new_ptr == NULL) OutOfMemory();
else array = new_ptr;
Consider sizing by the object than the type
// realloc(array,sizeof(Artist)*(*i)+1);
void *new_ptr = realloc(array, sizeof *array *((*i)+1));
All together
Artist *array = malloc(sizeof *array);
if (array == NULL) Handle_OutOfMemory();
...
void *new_ptr = realloc(array, sizeof *array * ((*i)+ 1));
if (new_ptr == NULL) {
// `array` still has *i elements assigned to it.
Handle_OutOfMemory();
} else {
array = new_ptr;
(*i)++;
}
realloc will attempt to resize your allocated memory in place if it can, but if there's not enough room to expand to the new size where it is, it will have to move the data to a new location. Realloc returns a pointer to the location for this reason. You should also test to make sure that it did not err. So something like this:
Artist *arr = malloc(sizeof(*arr) * i);
Artist *temp = realloc(arr, sizeof(Artist)*((*i)+1) // Borrowing this from Yunnosch
if(temp) {
arr = temp;
}
else {
free(arr);
// more error handling
}
Related
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)
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.
i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));
This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 8 years ago.
I want to make a function in C that would dynamically allocate memory for a pointer in parameter of the function.
#include <stdio.h>
#include <stdlib.h>
int allocate(char * arr, int size){
int code = -1;
arr = malloc(size);
if(arr != NULL) code = size;
return code;
}
void main(){
char * array;
if(allocate(array,4) != -1){
printf("allocated!\n");
if(array == NULL) printf("Oops it actually didn't allocate!\n");
}
}
When I execute the program; it will only display "allocated!" and "Oops it actually didn't allocate!". That means the memory allocation did happen (because the return code of the function is not -1. But then when I check if array is equal to NULL; it actually is!
This is a programming problem that I've had and sadly in some cases I can't use a workaround like this char * allocate(char * arr, int size); and assigning the return value to char * array.
You lack a level of indirection, you need char**.
Excuse the bad formatting, I write from my phone.
Char* array, array is bound to a memory slot (that will contain a value that points to another memory slot that would be interpreted as a char).
So you copy that value to the function and modify that value locally in allocate, but the modification never reaches the outside scope.
#include <stdio.h>
#include <stdlib.h>
int allocate(char ** arr, int size){
int code = -1;
*arr = malloc(size);
if(*arr != NULL) code = size;
return code;
}
void main(){
char * array;
if(allocate(&array,4) != -1){
printf("allocated!\n");
if(array == NULL) printf("Oops it actually didn't allocate!\n");
}
}
Not done C in something like 10 years but it should be OK.
You can allocate memory inside your function and return the address as shown below
There are also changes like instead of void main it should be int main()
#include <stdio.h>
#include <stdlib.h>
char *allocate( int size){
char *arr;
arr = malloc(size);
return arr;
}
int main(){
char * array;
if((array = allocate(4)) != NULL){
printf("allocated!\n");
}
return 0;
}
Arguments to functions in C are passed by value. This means following function has no sense:
void f(int x) {
x = 1;
}
int y = 0;
f(y);
// y is still 0
When f is invoked, y is copied to x. Any change to x changes that copy and won't affect y. To work around this, you need to either use return value or pass a pointer to y:
void f(int* x) {
*x = 1;
}
int y = 0;
f(&y);
// y is now 1
Here x is still a copy (of a pointer) but it points to y. Changes to x wont be visible outside that function. But changing *x modifies y.
The same rules apply to pointer arguments. You just need one more * for arguments you want to modify:
int allocate(char** arr, int size) {
*arr = malloc(size);
}
char *ptr;
allocate(&ptr);
Also note that checking array for NULL isn't sufficient here, because a locally defined variable could contain garbage value (thus, not being NULL). You have to assign NULL to it before the allocation:
char *array = NULL;
I want to create a new intarr_t with initial size len, but I've never handled this type of problem with a typedef'ed variable.
My problem is that intarr_create() should allocate the array space and then return a pointer to it if malloc was successful or a pointer to NULL if I failed. How can I fix this?
Also, why there is a * symbol in the function?
Here's my code:
#include <stdio.h>
typedef struct {
int* data;
unsigned int len;
} intarr_t;
intarr_t* intarr_create(unsigned int len) {
//intarr_t with initial size len
intarr_t = (int *) malloc(len); // not working here, can someone explain why?
if(intarr_t != NULL) {
return intarr_t;
} else {
return NULL;
}
}
int main() {
int len = 15;
int h = intarr_create(len);
printf("%d\n", h);
return 0;
}
It's not working because you did not give your variable a name. Also, int* and intarr_t are not the same type, so you will get a type mismatch unless you change the cast.
Rewrite your function into this:
intarr_t* intarr_create(unsigned int len)
{
intarr_t *result;
result = (intarr_t *)malloc(sizeof(intarr_t)); // allocate memory for struct
if(result != NULL)
{
result->data = (int *)malloc(len * sizeof(int)); // allocate memory for data
result->len = len;
if (result->data == NULL)
{
/* handle error */
}
}
else
{
/* handle error */
}
return (result);
}
You have to do a "double" malloc to get it right. First you have to allocate the memory for the intarr_t and if that was successful you have to allocate the memory for the data array.
Additionally malloc returns a void * which must be cast to the correct pointer type (should be a warning or maybe even an error with some compilers).
You have a few problems with your intarr_create function. First of all, you need to name your intarr_t variable. Now you have the slightly trickier problem of allocating memory for the actual array of integers in addition to your intarr structure. Remember, that you will have to call delete twice to destroy this object. Once on the data, and once on the actual structure itself.
intarr_t* intarr_create(unsigned int len)
{
intarr_t* array = (intarr_t*)malloc(sizeof(intarr_t));
array->data = (int*)malloc(len * sizeof(int));
return array;
}