I would like to realloc a 2D array. I have a counter, itime it increases each step. Each step, I would like to reallocate my array, keeping the old values, and add new values to the array. When itime=1, I use only malloc, because it is allocated for the first time. When itime increases (e.q. itime=2), realloc is used. In the realloc process my GUI crashes.
Can somebody tell me the reason of the crash, Have I reallocated correctly?
int itime;
char ** solpointer;
for( itime = 1 ; itime <= 4 ; itime++ ) {
if( itime == 1 ) {
solpointer = (char**)malloc(sizeof(char*) * itime);
solpointer[itime-1] = (char*)malloc(sizeof(char) * 32);
}
else {
solpointer = (char**)realloc(solpointer, sizeof(char*) * itime);
solpointer[itime-1] = (char*)malloc(sizeof(char) * 32 );
}
}
Related
I allocated a multi-dimensional array using malloc. After I process an element I have to delete it from the array and reallocate the correct amount of memory. So I used memmove to overwrite the array moving the elements that are in the next position with respect to the one I processed in its position.
float **dataset = (float**)malloc(CHUNK * sizeof(float *));
for (int i = 0; i < CHUNK; i++) {
dataset[i] = (float *) malloc((d + 1) * sizeof(float));
if(dataset[i] == NULL){
printf("Something went wrong in load_dataset(), memory allocation failed!");
exit(1);
}
}
[... filling the dataset and other stuff...]
/* now I want to move all the elements from the second one,
back of 1 position and then reallocate dataset
to have one less dimensoin*/
memmove(dataset[0], dataset[1], 20 * sizeof(float*));
But it only moves the first 4 elements.
How am I supposed to use dynamic memory allocations for arrays?
For example here is the following array in which i read individual words from a .txt file and save them word by word in the array:
Code:
char words[1000][15];
Here 1000 defines the number of words the array can save and each word may comprise of not more than 15 characters.
Now I want that that program should dynamically allocate the memory for the number of words it counts. For example, a .txt file may contain words greater that 1000. Now I want that the program should count the number of words and allocate the memory accordingly.
Since we cannot use a variable in place of [1000], I am completely blank at how to implement my logic. Please help me in this regard.
You use pointers.
Specifically, you use a pointer to an address, and using a standard c library function calls, you ask the operating system to expand the heap to allow you to store what you need to.
Now, it might refuse, which you will need to handle.
The next question becomes - how do you ask for a 2D array? Well, you ask for an array of pointers, and then expand each pointer.
As an example, consider this:
int i = 0;
char** words;
words = malloc((num_words)*sizeof(char*));
if ( words == NULL )
{
/* we have a problem */
printf("Error: out of memory.\n");
return;
}
for ( i=0; i<num_words; i++ )
{
words[i] = malloc((word_size+1)*sizeof(char));
if ( words[i] == NULL )
{
/* problem */
break;
}
}
if ( i != num_words )
{
/* it didn't allocate */
}
This gets you a two-dimensional array, where each element words[i] can have a different size, determinable at run time, just as the number of words is.
You will need to free() all of the resultant memory by looping over the array when you're done with it:
for ( i = 0; i < num_words; i++ )
{
free(words[i]);
}
free(words);
If you don't, you'll create a memory leak.
You could also use calloc. The difference is in calling convention and effect - calloc initialises all the memory to 0 whereas malloc does not.
If you need to resize at runtime, use realloc.
Malloc
Calloc
Realloc
Free
Also, important, watch out for the word_size+1 that I have used. Strings in C are zero-terminated and this takes an extra character which you need to account for. To ensure I remember this, I usually set the size of the variable word_size to whatever the size of the word should be (the length of the string as I expect) and explicitly leave the +1 in the malloc for the zero. Then I know that the allocated buffer can take a string of word_size characters. Not doing this is also fine - I just do it because I like to explicitly account for the zero in an obvious way.
There is also a downside to this approach - I've explicitly seen this as a shipped bug recently. Notice I wrote (word_size+1)*sizeof(type) - imagine however that I had written word_size*sizeof(type)+1. For sizeof(type)=1 these are the same thing but Windows uses wchar_t very frequently - and in this case you'll reserve one byte for your last zero rather than two - and they are zero-terminated elements of type type, not single zero bytes. This means you'll overrun on read and write.
Addendum: do it whichever way you like, just watch out for those zero terminators if you're going to pass the buffer to something that relies on them.
While Ninefingers provided an answer using an array of pointers , you can also use an array of arrays as long as the inner array's size is a constant expression. The code for this is simpler.
char (*words)[15]; // 'words' is pointer to char[15]
words = malloc (num_words * sizeof(char[15]);
// to access character i of word w
words[w][i];
free(words);
If you're working in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_LEN 15
int resizeArray(char (**wordList)[WORD_LEN], size_t *currentSize, size_t extent)
{
int result = 1;
char (*tmp)[WORD_LEN] = realloc(*wordList,
(*currentSize + extent) * sizeof **wordList);
if (tmp)
{
*currentSize += extent;
*wordList = tmp;
}
else
result = 0;
return result;
}
int main(void)
{
char *data[] = {"This", "is", "a", "test",
"of", "the", "Emergency",
"Broadcast", "System", NULL};
size_t i = 0, j;
char (*words)[WORD_LEN] = NULL;
size_t currentSize = 0;
for (i = 0; data[i] != NULL; i++)
{
if (currentSize <= i)
{
if (!resizeArray(&words, ¤tSize, 5))
{
fprintf(stderr, "Could not resize words\n");
break;
}
}
strcpy(words[i], data[i]);
}
printf("current array size: %lu\n", (unsigned long) currentSize);
printf("copied %lu words\n", (unsigned long) i);
for (j = 0; j < i; j++)
{
printf("wordlist[%lu] = \"%s\"\n", (unsigned long) j, words[j]);
}
free(words);
return 0;
}
If you intend to go for C++, STL is very useful for something dynamic allocation and is very easy. You can use std::vector ..
In modern C (C99) you have an additional choice, variable length arrays, VLA, such as that:
char myWord[N];
In principle you could also do such a thing in two dimensions, but if your sizes get too big, you may risk a stack overflow. In your case the easiest thing would be to use a pointer to such an array and to use malloc / realloc to resize them:
typedef char Word[wordlen];
size_t m = 100000;
Word* words = malloc(m * sizeof(Word));
/* initialize words[0]... words[m-1] here */
for (size_t i = 0; i < m; ++i) words[i][0] = '\0';
/* array is too small? */
m *= 2;
void *p = realloc(words, m*sizeof(Word));
if (p) words = p;
else {
/* error handling */
}
.
free(words);
This code should work (modulo typos) if wordlen is a constant or a variable, as long as you keep everything inside one function. If you want to place it in a function you should declare your function something like
void myWordFunc(size_t wordlen, size_t m, char words[m][wordlen]);
that is the length parameters must come first to be known for the declaration of words.
If the 15 in your example is variable, use one of the available answers (from Ninefingers or John Boker or Muggen).
If the 1000 is variable, use realloc:
words = malloc(1000 * sizeof(char*));
// ... read 1000 words
if (++num_words > 1000)
{
char** more_words = realloc(words, 2000 * sizeof(char*));
if (more_words) {printf("Too bad");}
else {words = more_words;}
}
In my code above, the constant 2000 is a simplification; you should add another variable capacity to support more than 2000 words:
if (++num_words > capacity)
{
// ... realloc
++capacity; // will reallocate 1000+ words each time; will be very slow
// capacity += 1000; // less reallocations, some memory wasted
// capacity *= 2; // less reallocations but more memory wasted
}
Here is a little information on dynamically allocating 2d arrays:
http://www.eskimo.com/~scs/cclass/int/sx9b.html
char ** words = malloc( 1000 * sizeof(char *));
int i;
for( i = 0 ; i < 1000 ; i++)
*(words+i) = malloc(sizeof(char) * 15);
//....
for( i = 0 ; i < 1000 ; i++)
free(*(words+i));
free(words);
So, I have a pointer which need to increase it's "length" until the user insert a negative number or "e". It starts with the length of "1", via a malloc() then I use into a do{...} while(...) loop the realloc() function to increase its lenght. Here's the code:
int *array = malloc (sizeof(int) * 1);
bool exit = false;
int lastIndex = 0, value;
do {
printf ("Insert a positive number. Insert a negative number or \"e\" to exit: ");
int scanf_result = scanf("%i", &value);
if (scanf_result) {
if (value >= 0) {
array[lastIndex] = value;
lastIndex++;
array = (int*) realloc (array, lastIndex * sizeof(int));
} else {
exit = true;
}
} else {
exit = true;
}
} while (!exit);
I can't figure out why after the 7th cicle it exit with the error realloc(): invalid next size.
Any idea? Thanks in advice for help.
You're not reallocating enough memory:
array = (int*) realloc (array, lastIndex * sizeof(int));
On the first iteration of the loop, lastIndex is incremented from 0 to 1, then you run the above realloc call. Since lastIndex is 1, you still only have enough space for 1 element. As a result, you write past the end of allocated memory on the next iteration.
This invokes undefined behavior, which in your case manifests as appearing to work properly for the first 6 iterations and failing on the 7th. It could have just as easily crashed on the first or second iteration.
Add one to the size you're allocating:
array = realloc(array, (lastIndex + 1) * sizeof(int));
Also, don't cast the return value of malloc/realloc.
Fix your realloc:
array = (int*) realloc (array, (lastIndex + 1) * sizeof(int))
You are allocating one item less than you need to.
I have a function which returns a multiple indirection pointer as result like so:
typedef struct {
int id;
char *name;
} user;
user **myfn(int users_count) {
user **a;
a = malloc(sizeof(user) * user_counts);
for(int i = 0 ; i<user_counts ; i++) {
*(a+i) = malloc(sizeof(user));
(*(a+i))->id = 1;
(*(a+i))->name = malloc(sizeof(char) * 25);
strncpy((*(a+i))->name, "Morteza", 25); // just for example
}
return a;
}
Now, I when I want to crawl in this result in main function, it will show all users name, but at the end it will encounter with Segmentation fault error.
int main() {
user **a = myfn(10);
int i = 0;
while((*(a+i)) != NULL) {
printf("ID: %d \t %s\n", (*(a+i))->id, (*(a+i))->name);
i++;
}
}
Results:
ID: 1 Morteza
ID: 2 Morteza
...
...
ID: 10 Morteza
Segmentation fault (core dumped)
Why condition of while doesn't work fine?
First of all,
a = malloc(sizeof(user) * user_counts);
has a problem - you want to allocate user_counts instances of pointers to user, not instances of user, so that line should be
a = malloc(sizeof(user *) * user_counts);
However, there's an easier way around this - the sizeof operator can take expressions as arguments as well as type names. So you can rewrite that line as
a = malloc( sizeof *a * user_counts );
The expression *a has type user *, so sizeof *a is equivalent to sizeof (user *). This makes your life a bit simpler, in that you don't have to puzzle out the type that a points to - make the compiler do the hard work.
You should always check the result of a malloc call.
a = malloc( sizeof *a * users_count );
if ( a )
{
// do stuff with a
}
Second of all, don't use *(a+i) to index into a - use a[i] instead. Makes things a bit easier to read. So,
*(a+i) = malloc(sizeof(user));
(*(a+i))->id = 1;
(*(a+i))->name = malloc(sizeof(char) * 25);
becomes
a[i] = malloc(sizeof *a[i]);
if ( a[i] )
{
a[i]->id = 1;
a[i]->name = malloc(sizeof *a[i]->name * 25);
}
else
{
/* deal with memory allocation failure */
}
Now, to your actual problem. Your code is crashing for one of the following reasons:
the initial malloc of a failed, so you're crashing on the first line that uses a[i];
the malloc of one of your a[i] failed, so you're crashing on a[i]->id = 1;
you've successfully allocated memory for all users_count elements of a - no a[i] is NULL, so you loop past the last element of your array and try to dereference the object immediately following it, which is most likely not a valid pointer.
In addition to adding the checks after each malloc call, you should probably loop based on users_count:
for ( i = 0; i < users_count; i++ )
printf("ID: %d \t %s\n", a[i]->id, a[i]->name);
Or, you need to allocate one extra element for a and set it to NULL:
a = malloc( sizeof *a * (users_count + 1) );
if ( a )
{
a[users_count] = NULL;
for ( i = 0; i < users_count; i++ )
...
}
Note that calloc initializes all allocated memory to 0, so you can use that and not worry about explicitly setting an element to NULL:
a = calloc( users_count + 1, sizeof *a );
if ( a )
{
for ( i = 0; i < users_count; i++ )
...
}
I'm trying to collect input integers one by one. My array starts with size 1 and I want to expand it by 1, with every input collected (is this a smart thing to do?)
Anyway, this is the code I managed to come up with, but it's not working as intended.
After this process, sizeof(array) always returns 8, which I assume means that the array is only being resized once. (sizeof(int) is 4 bits)
Trying to output the array results in multiple instances of the first input variable.
OUTPUT CODE
for(int s=0;s<sizeof(array)/sizeof(int);s++){
printf("%i\n",array[i]);
}
ORIGINAL CODE:
int i;
int size = 1;
int *array = malloc(size * sizeof(int));
int position = 0;
do{
i = getchar() - 48;
f (i != -16 && i != -38 && i != 0) {
array[position] = i;
position++;
size++;
*array = realloc(array, size * sizeof(int));
}
} while (i != 0);
UPDATED STILL NOT WORKING CODE
int i;
int size = 1;
int *array = malloc(size * sizeof(int));
int position = 0;
do{
i = getchar() - 48;
f (i != -16 && i != -38 && i != 0) {
array[position] = i;
position++;
size++;
array = realloc(array, size * sizeof(int));
}
} while (i != 0);
array = realloc(...)
not *array. Per the realloc docs, realloc returns the pointer, which you can store directly in your array pointer.
Edit One thing that will make your life easier: use char constants instead of raw numbers. E.g.,
i = getchar();
if(i != ' ' && i != '\n' && i != '0') {
/* 48-16 48-38 48-0 right? */
array[position] = i - '0'; /* '0' = 48 */
One thing that jumps out at me: inside your loop, this line:
*array = realloc(array, size * sizeof(int));
should instead be:
array = realloc(array, size * sizeof(int));
In the original version, you were sticking the result of realloc in the first element of the array by dereferencing the pointer first. Without the asterisk, you're reassigning the array itself.
(With some copy-paste from my comment:) sizeof(array) returns 8 because it equals sizeof(int*) (array is type int*) which is 8 (you're probably compiling as 64-bit). sizeof doesn't work how you think for pointers to arrays.
Similarly, your output code is wrong, for the same reason. You only print the first two elements because sizeof(array)/sizeof(int) will always be 8/4=2. It should be
for(int s=0;s<size;s++){
printf("%i\n",array[s]);
}
(note also changed index variable i to s)
where size is the variable from your other code chunk(s). You cannot find the length of the array from sizeof if it's dynamically allocated with pointers; that's impossible. Your code must "remember" the size of your array.