I have a user-defined struct call MyStruct and allocate a 2D dynamic array:
MyStruct** arr = (MyStruct**) malloc(sizeof(myStruct*)*size);
I want to process the array in a function:
void compute(MyStruct** lst)
{
int index = 0;
while(lst[index] != NULL)
{
//do something
index++;
}
}
I called compute(arr) and it works fine. But valgrind complains that there is an invalid read of size sizeof(MyStruct) at line while(...). I understand that at this point index is out of bound by 1 element. An easy fix is to pass size to the function and check if index < size through the loop.
Out of curiosity, is there anyway I can still traverse through the array without indexing that extra element AND not passing size to the function?
There is no standard way, no.
That said, there may be some nonstandard ways you can get the allocated size of a malloced piece of memory. For example, my machine has a size_t malloc_size(const void *); function in <malloc/malloc.h>; glibc has a malloc_usable_size function with a similar signature; and Microsoft’s libc implementation has an _msize function, also with a similar signature.
These cannot simply be dropped in, though; besides the obvious portability concerns, these return the actual amount of memory allocated for you, which might be slightly more than you requested. That might be okay for some applications, but perhaps not for iterating through your array.
You probably ought to just pass the size as a second parameter. Boring, I know.
Related
I have been writing a program where I have a 2d array that changes size if the user wants, as follows:
#include <stdlib.h>
#include <stdio.h>
int max_length = 1024;
int memory_length = 16;
int block_length = 64;
void process_input(int memory[memory_length][block_length], char* user_input) {
...
}
int main(void) {
printf("Not sure what to do? Enter 'help'\n");
while (0 == 0) {
int memory[memory_length][block_length];
char user_input[max_length];
printf(">> ");
fgets(user_input, max_length, stdin);
printf("\n");
process_input(memory, user_input);
if (user_input[0] == 'e' && user_input[1] == 'n' && user_input[2] == 'd') {
break;
}
printf("\n");
}
return 0;
}
NOTE: The process_input() function that I made allows the user to play around with the values inside the array 'memory' as well as change the value of memory_length or block_length, hence then changing the length of the array. After the user is done the cycle repeats with a fresh array.
I can use the 2d array perfectly fine, parsing it to any function. However one day I discover that there are functions such as malloc() that allow you to dynamically allocate memory through a pointer. This made me then question:
Should I re-write my whole very complicated program to use malloc and other 'memory functions', or is it okay to keep it this way?
Also as a side question that might be answered by answering the main question:
Every time I declare the 2d array, does the previous contents of the array get free, or do I keep filling up my memory like an amateur?
Finally if there is anything else that you may notice in the code or in my writing please let me know.
Thanks.
Should I re-write my whole very complicated program to use malloc and other 'memory functions', or is it okay to keep it this way?
Probably rewrite it indeed. int memory[memory_length][block_length]; in main() is a variable-length array (VLA). It is allocated with automatic storage and gets the size of those size variables at the point where its declaration is encountered, then it can't be resized from there.
For some reason a lot of beginners seem to think you can resize the VLA by changing the variables originally used to determine it's size, but no such magic relation between the VLA and those variables exists. How to declare variable-length arrays correctly?
The only kind of array in C that allows run-time resizing is one which was allocated dynamically. The only alternative to that is to allocate an array "large enough" and then keep track of how much of the array you actively are using - but it will sit there in memory (and that is likely no big deal).
However, it is not recommended to allocate huge arrays with automatic storage, since those usually end up on the stack and can cause stack overflows. Use either static storage duration or allocated storage (with malloc etc).
Every time I declare the 2d array, does the previous contents of the array get free, or do I keep filling up my memory like an amateur?
You can only declare it once. In case you do so inside a local scope, with automatic storage duration, it does indeed get cleared up every time you leave the scope which it was declared. But that also means that it can't be used outside that scope.
Finally if there is anything else that you may notice in the code or in my writing please let me know.
Yes, get rid of the global variables. There is no reason to use them in this example, avoid them like the plague. For example a function using an already allocated array might pass the sizes along, like in this example:
void process_input (size_t memory_length,
size_t block_length,
int memory[memory_length][block_length],
char* user_input)
In C, local variables, i.e. variables declared within a function, are allocated on the stack. They are only allocated once when the function is first called. The fact that you can declare variables within a while loop can lead to some confusion. The loop does not somehow allocate the memory again and again.
The memory allocated for all local variables is released when the function return.
The main reason that you might want declare a variable inside a loop (besides convenience) is to limit the scope of the variable. In your code above, you cannot access the "memory" variable outside of the while loop. You can easily check this for yourself. Your compiler should raise an error.
Whether the stack or the heap contains more memory depends on your computer architecture. In an embedded system you can often specify whether to allocate more or less memory to the heap or the stack. On a computer with virtual memory, such as a PC, the size of the heap and the stack are only limited by the size of your hard drive and the address space.
Allocating arrays on the heap is not as simple as it might seem. Single dimensional arrays work just as you might imagine, but things get more complicated with multidimensional arrays, so it is probably better to stick with either a locally or statically declared array in your case.
I want to add something to the end of the array passed to the function.
Which is better, declaring a new larger array or using alloc ()?
1.
void array_append(int *block, size_t size)
{
int new_block[size + 2];
memcpy(new_block, block, size);
(...append)
}
void array_append(int *block, size_t size)
{
int *new_block = calloc(1, sizeof(int) + 2);
memcpy(new_block, block, size);
(...append)
free(new_block);
}
I am not returning the newly created array anywhere.
I only use new_block inside functions.
Does not modify the original array in the function.
Declaring new_block as static is omitted.
I know how calloc() / malloc() works, I know that this operation has to be validated.
new_block is only meant to live in a function.
I just wonder which solution is better and why ...
regards
You should dynamically allocate an array instead of using a variable length array because in general in the last case the code can be unsafe due to a comparatively big size of the array that can lead to the stack overflow.
I want to add something to the end of the array
But you cannot really. Unless with realloc(). This is how your ...append trick can be done, whatever it means.
If you need a temporary array to work with and then copy into your array (but not at the end!), then all methods for allocation are allowed - it really depends on how often and with which sizes.
If it is called very often with limited sizes, it could be a static array.
There is no easy solution for growing arrays (or for memory management in general). At the extreme you allocate every element individually and link them together: a linked list.
--> avoid reaching the end of your arrays. Define a higher maximum or then implement a linked list.
In certain situations realloc() also makes sense (big changes in size, but not often). Problem is sometimes the whole array has to be memcopied to keep the larger array contiguous: "realloc", not "append". So it is "expensive".
I am not returning the newly created array anywhere.
That is part of the problem. You actually seem to be doing half of what realloc() does: allocate the new space, memcpy() the old contents...and then free the old and return the new array(-pointer) to the caller.
First version can not return the array pointer, because end of function is also end of local auto arrays, VLA or not.
If the append can be done to the existing array (which it can if the caller expects this and the memory of the array has room), you can merely append to the existing array.
Otherwise, you need a new array. In this case, the array must be returned to the caller. You can do this by returning a pointer to its first element or by having the caller pass a pointer to a pointer, and you modify the pointed-to pointer to point to the first element of the new array.
When you provide a new array, you must allocate memory for it with malloc or a similar routine. You should not use an array defined inside your function without static, as the memory for such an array is reserved only until execution of the function ends. When your function returns to the caller, that memory is released for other uses. (Generally, you also should not use an array declared with static, but for reasons involving good design, reducing bugs, and multiple serial or parallel calls to the function.)
I want to make a program which will say how many big and short letters is in the word and such, but run in to the problem I can't declare content of array dynamically. This is all C code.
I tried this:
char something;
scanf("%c",somethnig);
char somethingmore[]=something;
printf("%c",something[0])
but it wasn't possible to compile I also tried something like this:
char *something;
scanf("%c",something);
printf("%c",something[0]);
which was possible to compile but crushed when called array pointer(I apologize if the naming is wrong) I programing beginner so this is maybe silly question.
This is all just example of problem I run to not code of my program.
Well, disregarding the weirdly wrong syntax in your snippet, I think a good answer comes down to remind you of one thing:
C doesn't do any memory management for you.
Or, in other words, managing memory has to be done explicitly. As a consequence, arrays have a fixed size in C (must be known at compile time, so the compiler can reserve appropriate space in the binary, typically in a data segment, or on the stack for a local variable).
One notable exception is variable length arrays in c99, but even with them, the size of the array can be set only one time -- at initialization. It's a matter of taste whether to consider this a great thing or just a misfeature, but it will not solve your problem of changing the size of something at runtime.
If you want to dynamically grow something, there's only one option: make it an allocated object and manage memory for it yourself, using the functions malloc(), calloc(), realloc() and free(). All these functions are part of standard C, so you should read up on them. A typical usage (not related to your question) would be something like:
#include <stdlib.h>
int *list = 0;
size_t capacity = 0;
size_t count = 0;
void append(int value)
{
if (capacity)
{
if (count == capacity)
{
/* reserve more space, for real world code check realloc()
* return value */
capacity *= 2;
list = realloc(list, capacity * sizeof(int));
}
}
else
{
/* reserve an initial amount, for real world code check malloc()
* return value */
capacity = 16;
list = malloc(capacity * sizeof(int));
}
list[count++] = value;
}
This is very simplified, you'd probably define a container as a struct containing your pointer to the "array" as well as the capacity and count members and define functions working on that struct in some real world code. Or you could go and use predefined containers in a library like e.g. glib.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
If I need to write a function that returns an array: int*, which way is better?
int* f(..data..)
or: void f(..data..,int** arr)
and we call f like this: int* x; f(&x);. (maybe they are both the same but I am not sure. but if I need to return an ErrorCode(it's an enum) too, then in the first way f will get ErrorCode* and in the second way, f will return an ErrorCode).
Returning an array is just returning a variable amount of data.
That's a really old problem, and C programmers developed many answers for it:
Caller passes in buffer.
The neccessary size is documented and not passed, too short buffers are Undefined Behavior: strcpy()
The neccessary size is documented and passed, errors are signaled by the return value: strcpy_s()
The buffer size is passed by pointer, and the called function reallocates with the documented allocator as needed: POSIX getline()
The neccessary size is unknown, but can be queried by calling the function with buffer-length 0: snprintf()
The neccessary size is unknown and cannot be queried, as much as fits in a buffer of passed size is returned. If neccessary, additional calls must be made to get the rest: fread()
⚠ The neccessary size is unknown, cannot be queried, and passing too small a buffer is Undefined Behavior. This is a design defect, therefore the function is deprecated / removed in newer versions, and just mentioned here for completeness: gets().
Caller passes a callback:
The callback-function gets a context-parameter: qsort_s()
The callback-function gets no context-parameter. Getting the context requires magic: qsort()
Caller passes an allocator: Not found in the C standard library. All allocator-aware C++ containers support that though.
Callee contract specifies the deallocator. Calling the wrong one is Undefined Behavior: fopen()->fclose() strdup()->free()
Callee returns an object which contains the deallocator: COM-Objects
Callee uses an internal shared buffer: asctime()
Be aware that either the returned array must contain a sentinel object or other marker, you have to return the length separately, or you have to return a struct containing a pointer to the data and the length.
Pass-by-reference (pointer to size or such) helps there.
In general, whenever the user has to guess the size or look it up in the manual, he will sometimes get it wrong. If he does not get it wrong, a later revision might invalidate his careful work, so it doesn't matter he was once right. Anyway, this way lies madness (UB).
For the rest, choose the most comfortable and efficient one you can.
Regarding an error code: Remember there's errno.
Usually it's more convenient and semantic to return the array
int* f(..data..)
If ever you need complexe error handling (e.g., returning errors values), you should return the error as an int, and the array by value.
There is no "better" here: you decide which approach fits the needs of the callers better.
Note that both functions are bound to give a user an array that they allocate internally, so deallocating the resultant array becomes a responsibility of the caller. In other words, somewhere inside f() you would have a malloc, and the user who receives the data must call free() on it.
You have another option here - let the caller pass the array into you, and return back a number that says how many items you put back into it:
size_t f(int *buffer, size_t max_length)
This approach lets the caller pass you a buffer in a static or in the automatic memory, thus improving flexibility.
the classic model is (assuming you need to return error code too)
int f(...., int **arr)
even though it doesnt flow so nicely as a function returning the array
Note this is why the lovely go language supports multiple return values.
Its also one of the reasons for exceptions - it gets the error indicators out of the function i/o space
The first one is better if there is no requirement to deal with an already existent pointer in the function.
The second one is used when you already have a defined pointer that points to an already allocated container (for example a list) and inside the function the value of the pointer can be changed.
If you must call f like int* x; f(&x);, you do not have much of a choice. You must use the second syntax, i.e., void f(..data..,int** arr). This is because you are not using return value anyways in your code.
The approach depends on a specific task and perhaps on your personal taste or a coding convention adopted in your project.
In general, I'd like to pass pointers as "output" parameters instead of return'ing an array for a number of reasons.
You likely want to return a number of elements in the array together with the array itself. But if you do this:
int f(const void* data, int** out_array);
Then if you see the signature first time, you can't quite tell what the function returns, the number of elements, or an error code, so I prefer to do this:
void f(const void* data, int** out_array, int* out_array_nelements);
Or even better:
void f(const void* data, int** out_array, size_t* out_array_nelements);
The function signature must be self-explanatory, and the parameter names help to achieve that.
The output array needs to be stored somewhere. You need to allocate some memory for the array. If you return a pointer to the array without passing the same pointer as argument, then you can't allocate memory on the stack. I mean, you cannot do this:
int f (const void *data) {
int array[10];
return array; /* the array is likely deallocated when the function exits */
}
Instead, you have to do static int array[10] (which is not thread-safe) or int *array = malloc(...) which leads to memory leaks.
So I suggest you to pass a pointer to the array which is already allocated before the function call, like this:
void f(const void *data, int* out_array, size_t* out_nelements, size_t max_nelements);
The benefit is you are free to choose where to allocate the array:
On the stack:
int array[10] = { 0 };
size_t max_nelements = sizeof(array)/sizeof(array[0]);
size_t nelements = 0;
f(data, array, &nelements, max_nelements);
Or in the heap:
size_t nelements = 0;
size_t max_nelements = 10;
int *array = malloc(max_nelements * sizeof(int));
f(data, array, &nelements, max_nelements);
See, with this approach you are free to choose how to allocate the memory.
May be similar question found on SO. But, I didn't found that, here is the scenario
Case 1
void main()
{
char g[10];
char a[10];
scanf("%[^\n] %[^\n]",a,g);
swap(a,g);
printf("%s %s",a,g);
}
Case 2
void main()
{
char *g=malloc(sizeof(char)*10);
char *a=malloc(sizeof(char)*10);
scanf("%[^\n] %[^\n]",a,g);
swap(a,g);
printf("%s %s",a,g);
}
I'm getting same output in both case. So, my question is when should I prefer malloc() instead of array or vice-verse and why ?? I found common definition, malloc() provides dynamic allocation. So, it is the only difference between them ?? Please any one explain with example, what is the meaning of dynamic although we are specifying the size in malloc().
The principle difference relates to when and how you decide the array length. Using fixed length arrays forces you to decide your array length at compile time. In contrast using malloc allows you to decide the array length at runtime.
In particular, deciding at runtime allows you to base the decision on user input, on information not known at the time you compile. For example, you may allocate the array to be a size big enough to fit the actual data input by the user. If you use fixed length arrays, you have to decide at compile time an upper bound, and then force that limitation onto the user.
Another more subtle issue is that allocating very large fixed length arrays as local variables can lead to stack overflow runtime errors. And for that reason, you sometimes prefer to allocate such arrays dynamically using malloc.
Please any one explain with example, what is the meaning of dynamic although we are specifying the size.
I suspect this was significant before C99. Before C99, you couldn't have dynamically-sized auto arrays:
void somefunc(size_t sz)
{
char buf[sz];
}
is valid C99 but invalid C89. However, using malloc(), you can specify any value, you don't have to call malloc() with a constant as its argument.
Also, to clear up what other purpose malloc() has: you can't return stack-allocated memory from a function, so if your function needs to return allocated memory, you typically use malloc() (or some other member of the malloc familiy, including realloc() and calloc()) to obtain a block of memory. To understand this, consider the following code:
char *foo()
{
char buf[13] = "Hello world!";
return buf;
}
Since buf is a local variable, it's invalidated at the end of its enclosing function - returning it results in undefined behavior. The function above is erroneous. However, a pointer obtained using malloc() remains valid through function calls (until you don't call free() on it):
char *bar()
{
char *buf = malloc(13);
strcpy(buf, "Hello World!");
return buf;
}
This is absolutely valid.
I would add that in this particular example, malloc() is very wasteful, as there is more memory allocated for the array than what would appear [due to overhead in malloc] as well as the time it takes to call malloc() and later free() - and there's overhead for the programmer to remember to free it - memory leaks can be quite hard to debug.
Edit: Case in point, your code is missing the free() at the end of main() - may not matter here, but it shows my point quite well.
So small structures (less than 100 bytes) should typically be allocated on the stack. If you have large data structures, it's better to allocate them with malloc (or, if it's the right thing to do, use globals - but this is a sensitive subject).
Clearly, if you don't know the size of something beforehand, and it MAY be very large (kilobytes in size), it is definitely a case of "consider using malloc".
On the other hand, stacks are pretty big these days (for "real computers" at least), so allocating a couple of kilobytes of stack is not a big deal.