This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 4 years ago.
I have written some code in C by taking the maximum size of char array as 100. It worked well. But when I increase the maximum size of char array to 10000 it gives me segmentation fault(as it has exceeded its limit). Can someone tell me how can I increase the maximum size and store a string of length 10000.
i.e How can I take the "char a[100]" as "char a[10000]" and execute the same code????
You can allocate the array dynamically:
#include <stdlib.h>
char *a = malloc(100*sizeof(char));
if (a == NULL)
{
// error handling
printf("The allocation of array a has failed");
exit(-1);
}
and when you want to increase its size:
tmp_a = realloc(a, 10000*sizeof(char));
if ( tmp_a == NULL ) // realloc has failed
{
// error handling
printf("The re-allocation of array a has failed");
free(a);
exit(-2);
}
else //realloc was successful
{
a = tmp_a;
}
Eventually, remember to free the allocated memory, when the array is not needed anymore:
free(a);
Basically realloc(prt, size) returns a pointer to a new memory block that has the size specified by size and deallocates the block pointed to by ptr. If it fails, the original memory block is not deallocated.
Please read here and here for further info.
Related
I have a char array, we know that that a char size is 1 byte. Now I have to collect some char -> getchar() of course and simultaneously increase the array by 1 byte (without malloc, only library: stdio.h)
My suggestion would be, pointing to the array and somehow increase that array by 1 till there are no more chars to get OR you run out of Memory...
Is it possible to increase char array while using it, WITHOUT malloc?
No.
You cannot increase the size of a fixed size array.
For that you need realloc() from <stdlib.h>, which it seems you are not "allowed" to use.
Is it possible to increase char array while using it, WITHOUT malloc?
Quick answer: No it is not possible to increase the size of an array without reallocating it.
Fun answer: Don't use malloc(), use realloc().
Long answer:
If the char array has static or automatic storage class, it is most likely impossible to increase its size at runtime because keeping it at the same address that would require objects that are present at higher addresses to be moved or reallocated elsewhere.
If the array was obtained by malloc, it might be possible to extend its size if no other objects have been allocated after it in memory. Indeed realloc() to a larger size might return the same address. The problem is it is impossible to predict and if realloc returns a different address, the current space has been freed so pointers to it are now invalid.
The efficient way to proceed with this reallocation is to increase the size geometrically, by a factor at a time, 2x, 1.5x, 1.625x ... to minimize the number of reallocations and keep linear time as the size of the array grows linearly. You would a different variable for the allocated size of the array and the number of characters that you have stored into it.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *a = NULL;
size_t size = 0;
size_t count = 0;
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (count >= size) {
/* reallocate the buffer to 1.5x size */
size_t newsize = size + size / 2 + 16;
char *new_a = realloc(a, new_size);
if (new_a == NULL) {
fprintf("out of memory for %zu bytes\n", new_size);
free(a);
return 1;
}
a = new_a;
size = new_size;
}
a[count++] = c;
}
for (i = 0; i < count; i++) {
putchar(a[i]);
}
free(a);
return 0;
}
There are two ways to create space for the string without using dynamic memory allocation(malloc...). You can use a static array or an array with automatic storage duration, you need to specify a maximum amount, you might never reach. But always check against it.
#define BUFFER_SIZE 0x10000
Static
static char buffer[BUFFER_SIZE];
Or automatic (You need to ensure BUFFER_SIZE is smaller than the stack size)
int main() {
char buffer[BUFFER_SIZE];
...
};
There are also optimizations done by the operating system. It might lazily allocate the whole (static/automatic) buffer, so that only the used part is in the physical memory. (This also applies to the dynamic memory allocation functions.) I found out that calloc (for big chunks) just allocates the virtual memory for the program; memory pages are cleared only, when they are accessed (probably through some interrupts raised by the cpu). I compared it to an allocation with malloc and memset. The memset does unnessecary work, if not all bytes/pages of the buffer are accessed by the program.
If you cannot allocate a buffer with malloc..., create a static/automatic array with enough size and let the operating system allocate it for you. It does not occupy the same space in the binary, because it is just stored as a size.
This question already has answers here:
Using sizeof with a dynamically allocated array
(5 answers)
Closed 5 years ago.
I´m working on my program, that loads data from external .txt file - it is structure of 3 integers. Now Im struggling with function that allocates memory. I want to allocate memory for structure of 9 members (108 bytes).
My main program was too large to mess with so I created a smaller program to help me more easily figure out what is going on. Previous questions I went through seemed too complicated and unclear to me, that´s why I made my own.
Id like to know why the third printf, prints 4 and how to correctly allocate required memory (108 bytes)
Glad for any advice
#include <stdio.h>
#include <math.h>
int main(){
int object_counter = 9;
typedef struct myStruct {
int name;
int age;
int height;
} myStruct;
myStruct* dynamicStruct;
dynamicStruct = malloc(object_counter*sizeof(myStruct));
if (dynamicStruct == NULL) {
printf("ERROR\n");
return (-1);
} else {
printf("SUCCESS\n");
}
printf("Size is: %lu\n", sizeof(myStruct)); // prints 12, thats 3 times int, OK
printf("Size is: %lu\n", object_counter*sizeof(struct myStruct)); // prints 108, obviously 9 times 4 bytes
printf("Size is: %lu\n", sizeof(dynamicStruct)); // prints 4 ?? (expected 108)
return 0;
}
The sizeof any pointer is constant (8 bytes on my Linux/x86-64 system, which is also the sizeof(uintptr_t), etc....). It is unrelated to the runtime size of the pointed memory zone. In other words, the sizeof operator always gives a compile-time constant (except for VLAs).
You practically need to keep elsewhere the allocated size of a malloc-ed pointer. For example, you could keep the pointer value in one variable, and its allocated size in another variable.
You could consider an abstract data type (using flexible array members) approach like here.
This question already has answers here:
Initially mallocate 0 elements to later reallocate and measure size
(2 answers)
Closed 6 years ago.
Below code is just an example which I use to come to the point later:
/* Extract digits from an integer and store in an array in reverse order*/
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int oct=316;
int* array=malloc(0*sizeof(int*)); //Step 1
int* temp;
size_t size=0;
while(oct/10>0 || oct%10>0){
temp=realloc(array,++size*sizeof(int)); // Step2 requires Step1
if(temp==NULL){
printf("Can't reallocate memory");
exit(-1);
}
else{
array=temp;
}
array[size-1]=oct%10;
oct/=10;
}
for(int i=0;i<size;i++)
printf("%d\n",array[i]);
return 0;
}
The realloc reference [1] states :
Reallocates the given area of memory. It must be previously allocated
by malloc(), calloc(), realloc()...
Initially I compiled the code without step1 and on running it I got a segmentation fault. Then I included step1, now the code compiles fine. I don't want to allocate some space without finding an integer to store so I have used a size of zero with malloc. However malloc reference [2] states :
If size is zero, the return value depends on the particular library
implementation (it may or may not be a null pointer), but the returned
pointer shall not be dereferenced.
Now, I doubt my implementation is portable. How can I work around this issue?
I tried doing int* array=NULL; but I got a segmentation fault.
You can initiate array to NULL. In the man page for realloc(void *ptr, size_t size) you can read:
If ptr is NULL, then the call is equivalent to malloc(size)
Moreover realloc does not change its parameter. It returns pointer to newly allocated/reallocated space. So, for reallocating you shall use a code like:
array = realloc(array,(++size)*sizeof(int));
if (array == NULL) { some error; }
I'm a beginner of C and now I'm learning pointer and dynamic memory allocation. I want to write a simple program to create empty arrays and check for the existence of a given number. Here's my code:
/* create an empty array pointer */
int* createArray(){
int *a = (int*) malloc(sizeof(int));
return a;
}
void findArrayElement(int *list, int element){
int i;
int len = (sizeof(list) / sizeof(int));
if (sizeof(list) == 0) {
printf("NO\n");
return;
}
for (i=0; i<len; i++) {
if (list[i] == element) {
printf("YES\n");
return;
}
}
printf("NO\n");
}
int main(int argc, const char * argv[]) {
int *p;
p = createArray();
printf("size of int is: %lu\n", sizeof(int));
printf("size of p is: %lu\n", sizeof(p));
printf("LENGTH of p is: %lu\n", ARRLENGTH(p));
findArrayElement(p, 2);
findArrayElement(p, 0);
return 0;
}
But when I run the program, I always get 'YES' when I looking for 0, so
Is there a way to differentiate integer 0 and a complete empty array?
Also I'm not sure whether my function createArray() is a correct way to create an empty array.
Thanks guys.
Is there a way to differentiate integer 0 and a complete empty array?
How do you define an empty array? Once you allocate a memory chunk and assign it to a pointer, it already has some value (which is undefined in case of alloc). The most used way to mark a pointer as not used or not allocated os to assign NULL to it.
Also I'm not sure whether my function createArray() is a correct way to create an empty array.
sizeof returns the number of bytes which the given object (or type) occupies in the memory. In your case sizeof(list) returns 8 as it is a pointer.
In oder to allocate an array, the function has to receive its size. Currently it always allocates size for one integer only.
Edit: Adding example.
/* create an empty array pointer */
int* createArray(size_t size)
{
return (size ? (int*) malloc(sizeof(int)*size) : NULL);
}
So now the returned pointer should be 'coupled' with the size of the array. Which means that each function that receives an array as a parameter should receive also its size.
sizeof returns the memory size of the array pointer, regardless of contents.
edit: if it exists in memory, it will be nonzero.
edit 3: removed inaccurate information, see the comments about creating a variable to record the length. Also from comments, note that your createArray function is creating an array for exactly 1 integer. In C, arrays are of fixed length. So this Array will always be the same size (whether you stored something in it or not). sizeof(pointer) will always return the memory allocated for the pointer, not the memory allocated for the array at which it is pointing.
On RHEL6, I'm facing a strange problem with realloc(). At some point in the program, realloc() returns NULL (the old pointer has an address and there's plently of memory available). What's being allocated is 200 structure elements (structure below). For some reason, when I do a realloc() instead, it works, but I then have to assign the old pointer to the new one. Below is a simplified version of my code.
This is perhaps a server tuning issue more than a programming one. What is your opinion?
Thanks.
//hearder file
typedef struct { /* Variable Node Detail Record */
long next;
long mask;
char *value;
// more stuff...
} NODETEST;
extern NODETEST *oldNodes;
extern NODETEST *newNodes;
//program
#define MAXSIZE 200
// do some stuff with oldNodes....
int alloc_nodes (void)
{
// Allocate or grow the table
oldNodes = (NODETEST *) malloc(MAXSIZE * sizeof(NODETEST));
if( oldNodes == NULL ) {
//handle exception...
exit(1);
}
//oldNodes = (NODETEST *) realloc(oldNodes,MAXSIZE * sizeof(NODETEST)); // *** FAILS
newNodes = (NODETEST *) realloc(oldNodes,MAXSIZE * sizeof(NODETEST)); // *** WORKS
if( newNodes == NULL ){
printf("errno=%d\n", errno );
}else{
oldNodes = newNodes; }
}
Your first call malloc with a size S and then realloc with the same size S. This is wrong: you have to pass to realloc the new wanted size (independently of the current size - it is not an increment). Here, there is a big chance realloc returns exactly the same pointer it received. BTW it is not clear why you want to do with a malloc immediately followed by a realloc. Gives us more detail.
If you want a dynamic table whose size auto-adjusts, you need to allocate an initial size storing its size in a variable (e.g. alloc_size) and keep the current number of occupied elements in another variable (e.g. n_elem) . When you add an element you increment this number. When the table is full reallocate it. Here is a sketch
NODETEST *newNodes = NULL;
int allocated_elem = 0;
int n_elem = 0;
#define ALLOC_INCR 200
then at each addition:
if (n_elem >= alloc_size) { // the first time realloc is as malloc since nodes == NULL
alloc_size += ALLOC_INCR;
nodes = (NODETEST *) realloc(nodes, alloc_size * sizeof(NODETEST));
if (nodes == NULL) {
//handle exception...
exit(1);
}
}
// add your element at nodes[n_elem]
n_elem++;
Recall that realloc acts like malloc when the received pointer is NULL (case of the first call). Thus it allocates the initial table. Subsequent calls reallocate it by adjusting the size with a constant increment (here 200). Some other schemes are possible for the enlargement of the table, for instance you can multiply the size by a factor (e.g. 2) starting from 32:
if (n_elem >= alloc_size) { // the first time realloc is as malloc since nodes == NULL
alloc_size = (alloc_size == 0) ? 32 : alloc_size * 2;
Regarind the FAIL and WORKS comments: it is clear that if you assign oldNodes (in the FAIL code) then newNodes is not assigned and keeps its initial value which is zero (NULL) since it is declared as a global variable and not initialized (well I suppose, it is extern here). Thus the test if (newNodes == NULL) will probably fail.