libmpdec mpd_qncopy memory allocation - c

https://www.bytereef.org/mpdecimal/doc/libmpdec/assign-convert.html
mpd_t *mpd_qncopy(const mpd_t *a);
Returns a pointer to a fresh copy of a, NULL on failure.
What does "a fresh copy" mean?
Where does it allocate the new pointer without any mpd_context_t given?

"Fresh copy" means allocate memory and copy the decimal object over. The full implementation is:
mpd_t *
mpd_qncopy(const mpd_t *a)
{
mpd_t *result;
if ((result = mpd_qnew_size(a->len)) == NULL) {
return NULL;
}
memcpy(result->data, a->data, a->len * (sizeof *result->data));
mpd_copy_flags(result, a);
result->exp = a->exp;
result->digits = a->digits;
result->len = a->len;
return result;
}
It is unclear why you think an mpd_context_t object would need to be provided, as no operation is performed on the decimal.

Related

Passing pointer to pointer for reallocation in function

I'm a beginner C programmer and have issues implementing an (ordered) dynamic array of structs.
Before adding an element to the array, I want to check if it is full and double it's size in that case:
void insert_translation(dict_entry **dict, char *word, char *translation){
if( dictionary_entries == dictionary_size ){
dict_entry *temp_dict;
temp_dict = realloc(&dict, (dictionary_size *= 2) * sizeof(dict_entry) );
// printf("Increased dict size to %d\n", dictionary_size);
// if(temp_dict == NULL){
// fprintf(stderr, "Out of memory during realloc()!\n");
// /*free(dict);
// exit(EXIT_OUT_OF_MEMORY);*/
// }
//free(dict);
//*dict = temp_dict;
}
dictionary_entries++;
printf("Inserted %s into dict - %d of %d filled.\n", word, dictionary_entries, dictionary_size);
}
I call the function from the main function like this:
dictionary_size = 2; //number of initial key-value pairs (translations)
dictionary_entries = 0;
dict_entry *dictionary = malloc(dictionary_size * sizeof(dict_entry));
[...]
insert_translation(&dictionary, "bla", "blub");
In my understanding, dictionary is a pointer to a space in memory. &dictionary is a pointer to the pointer, which I pass to the function. In the function, dict is said pointer to pointer, so &dict should be the pointer to the area in memory? However, when I try to compile, I get the following error message:
pointer being realloc'd was not allocated
Edit
I expanded the code sample to show more of the code in the main function.
The problem is in this statement
temp_dict = realloc(&dict, (dictionary_size *= 2) * sizeof(dict_entry) );
The parameter dict has the type
dict_entry **dict
in the statement that reallocs the memory you have to use the value of the pointer *dic but you are uisng an expression &dict that has the type dict_entry ***.
Compare the type of the left side of the assignment
ict_entry *temp_dict
with the type of the reallocated pointer. They should be the same (except in C one of them can have the type void *)
So you need to write
temp_dict = realloc(*dict, (dictionary_size *= 2) * sizeof(dict_entry) );
^^^^^
In C arguments are passed by value. If you want to change the original value of an argument you should to pass it by reference through a pointer to the argument. In the function you need to dereference the pointer that to change the object pointed to by the pointer.
&dict -> *dict. You can simplify the code by using a return type, to avoid such bugs:
dict_entry* insert_translation(dict_entry* dict, char *word, char *translation)
{
...
if( dictionary_entries == dictionary_size )
{
dictionary_size *= 2;
dict_entry *tmp = realloc(dict, sizeof(dict_entry[dictionary_size]));
if(tmp == NULL)
{
// error handling, free(dict) etc
}
else
{
dict = tmp;
}
}
...
return dict;
}

Correct use of Realloc

This is the way I've been taught to use realloc():
int *a = malloc(10);
a = realloc(a, 100); // Why do we do "a = .... ?"
if(a == NULL)
//Deal with problem.....
Isn't that redundant? Can't i just do something like this? :
if(realloc(a, 100) == NULL) //Deal with the problem
Same for other realloc examples i've found around, for example:
int *oldPtr = malloc(10);
int * newPtr = realloc(oldPtr, 100);
if(newPtr == NULL) //deal with problems
else oldPtr = newPtr;
Can't i just do this instead? :
int *oldPtr = malloc(10);
if(realloc(oldPtr, 100) == NULL) //deal with problems
//else not necessary, oldPtr has already been reallocated and has now 100 elements
realloc returns a pointer to the resized buffer; this pointer value may be different from the original pointer value, so you need to save that return value somewhere.
realloc may return NULL if the request cannot be satsified (in which case the original buffer is left in place). For that reason, you want to save the return value to a different pointer variable than the original. Otherwise, you risk overwriting your original pointer with NULL and losing your only reference to that buffer.
Example:
size_t buf_size = 0; // keep track of our buffer size
// ...
int *a = malloc(sizeof *a * some_size); // initial allocation
if (a)
buf_size = some_size;
// ...
int *tmp = realloc(a, sizeof *a * new_size); // reallocation
if (tmp) {
a = tmp; // save new pointer value
buf_size = new_size; // and new buffer size
}
else {
// realloc failure, handle as appropriate
}
the correct way to call realloc is to save the return value in a temporary variable and check it for NULL. That way if realloc has failed, you haven't lost your original memory. For example:
int *a, *b;
a = malloc(10);
b = realloc(a, 100);
if (b == NULL) {
// handle error and exit
}
a = b;
EDIT: Note that if the error handling doesn't exit, you should put the last line above, i.e. a = b; inside an else clause.
realloc on failure keeps the original pointer and size. realloc on success may not (and often does not) return the exact same pointer as the input.
So the proper solution is your third example.
int *oldPtr = malloc(10);
int * newPtr = realloc(oldPtr, 100);
if(newPtr == NULL) //deal with problems
else oldPtr = newPtr;
This code snippet is wrong.
int *a = malloc(10);
a = realloc(a, 100); // Why do we do "a = .... ?"
if(a == NULL)
//Deal with problem.....
If the call of realloc returns NULL then the previous value of the pointer a is lost. So there can be a memory leak because it will be impossible to free the memory allocated by the call of malloc.
If just to write
if(realloc(a, 100) == NULL) //Deal with the problem
then in turn the returned pointer of the call of the realloc can be lost.
This code snippet
int *oldPtr = malloc(10);
int * newPtr = realloc(oldPtr, 100);
if(newPtr == NULL) //deal with problems
else oldPtr = newPtr;
is correct. However if to write
int *oldPtr = malloc(10);
if(realloc(oldPtr, 100) == NULL) //deal with problems
//else not necessary, oldPtr has already been reallocated and has now 100 elements
then again the returned pointer of the call of realloc can be lost.
From the description of realloc in the C Standard (7.22.3.5 The realloc function)
4 The realloc function returns a pointer to the new object (which may
have (or may not have - added by me) the same value as a pointer to the
old object, or a null pointer if the new object could not be
allocated.

Strange behaviour on Realloc: invalid next size [duplicate]

This question already has an answer here:
free char*: invalid next size (fast) [duplicate]
(1 answer)
Closed 8 years ago.
I know there are tons of other realloc questions and answers and I have read almost all of them, but I still couldn't manage to fix my problem.
I decided to stop trying when I accidentaly discovered a very strange behaviour of my code.
I introduced a line to try something, but although I don't use the value of newElems in main, the line changes the behaviour.
When the line is commented, the code fails at first realloc. Including the line, the first realloc works. (it still crashes on the second one).
Any ideas on what might be happening?
int main(int argc, char** argv) {
Pqueue q = pqueue_new(3);
Node a = {.name = "a"}, b = {.name = "b"},
c = {.name = "c"}, d = {.name = "d"};
push(& q, & a, 3);
// the next one is the strange line: as you can see, it doesn't modify q
// but commenting it out produces different behaviour
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
push(& q, & b, 5);
push(& q, & c, 4);
char s[5];
Node* n;
for (int i = 1; i <= 65; ++i) {
sprintf(s, "%d", i);
n = malloc(sizeof *n);
n->name = strdup(s);
push(& q, n, i);
}
Node* current = NULL;
while ((current = pop(& q))) {
printf("%s ", current->name);
}
return 0;
}
and the push function:
void push(Pqueue* q, Node* item, int priority) {
if (q->size >= q->capacity) {
if (DEBUG)
fprintf(stderr, "Reallocating bigger queue from capacity %d\n",
q->capacity);
q->capacity *= 2;
Pqueue_elem* newElems = realloc(q->elems,
q->capacity * sizeof *newElems);
check(newElems, "a bigger elems array");
q->elems = newElems;
}
// append at the end, then find its correct place and move it there
int idx = ++q->size, p;
while ((p = PARENT(idx)) && priority > q->elems[p].priority) {
q->elems[idx] = q->elems[p];
idx = p;
}
// after exiting the while, idx is at the right place for the element
q->elems[idx].data = item;
q->elems[idx].priority = priority;
}
The pqueue_new function:
Pqueue pqueue_new(unsigned int size) {
if (size < 4)
size = 4;
Pqueue* q = malloc(sizeof *q);
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
return *q;
}
realloc will change the amount of memory that is allocated, if needed. It is also free to move the data to another place in memory if that's more efficient (avoiding memory fragmentation).
The function, then, returns a new pointer to the new location in memory where your data is hiding. You're calling realloc, and allocating (probably) four times as much memory as before, so it's very likely that that allocated memory is situated elsewhere in memory.
In your comment, you said realloc works like free + malloc. Well, in some cases it can behave similarly, however: realloc and free are different functions, that do different tasks. Both are functions that manage the dynamic memory, so yes, obviously there are similarities, and in the case of realloc, sometimes they can seem to be doing the same thing, however: As I explained here, realloc and free are fundamentally different functions
However, by not assigning the return value of realloc to q.elems, you're left with a pointer to a memory address that is no longer valid. The rest of your program can, and probably does, exhibit signs of undefined behaviour, then.
Unless you show some more code, I suspect this will take care of the problem:
//change:
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
//to
q.elems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
Or better yet, check for NULL pointers:
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
if (newElems == NULL)
exit( EXIT_FAILURE );// + fprintf(stderr, "Fatal error...");
q.elems = newElems;//<-- assign new pointer!
Looking at your pqueue_new function, I would suggest a different approach. Have it return the pointer to Pqueue. You're working with a piece of dynamic memory, treat it accordingly, and have your code reflect that all the way through:
Pqueue * pqueue_new(size_t size)
{//size_t makes more sense
if (size < 4)
size = 4;
Pqueue* q = malloc(sizeof *q);
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
return q;
}
Alternatively, pass the function a pointer to a stack variable:
void pqueue_new(Pqueue *q, size_t size)
{
if (q == NULL)
{
fprintf(stderr, "pqueue_new does not do NULL pointers, I'm not Chuck Norris");
return;//or exit
}
if (size < 4)
size = 4;
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
}
//call like so:
int main ( void )
{
Pqueue q;
pqueue_new(&q, 3);
}
Those would be the more common approaches.
Thank you all for the suggestions! I wouldn't have solved it without them,
The strange behaviour was caused by an off by one error. I was reallocating the queue only when q->size >= q->capacity, but since q was indexed from 0, it meant that before realloc I was writing in a forbidden location (q->elems[q->size]), which messed everything up.

error: "pointer being freed was not allocated" in c

this error is always fired, when i'm try to free my allocated struct the second time, which it shouldn't, because the struct is set to NULL after i'm freeing it.
here's my struct with no real pointer inside it:
typedef struct{
int frame;
double timestamp;
int identifier;
int state;
int unknown1;
int unknown2;
mtVector normalized;
float size;
int unknown3;
float angle;
float majorAxis;
float minorAxis;
mtVector unknown4;
int unknown5[2];
float unknown6;
}Touch;
the barebone main function:
int main(){
Touch *myTouch = NULL;
int inputCounter = 0;
//whenever a touch is recognized:
...
myTouch = (Touch*)realloc(myTouch,sizeof(Touch)*(inputCounter++));
...
// everything works fine until:
freeTouch(myTouch);
}
void freeTouch(Touch *f){
if(f != NULL){
free(f);
f = NULL;
}
}
anybody got an idea?
f is a local variable. free(f) will affect the allocated memory, but f = NULL has no impact on myTouch in freeTouch(myTouch);.
Try
void freeTouch(Touch **f){
if(*f != NULL){
free(*f);
*f = NULL;
}
}
instead and use freeTouch(&myTouch).
You have two problems there. The first is that it's not a good idea to explicitly cast the return value from malloc or realloc. Doing so can cause problems if you forget to include the prototype/header for it.
Secondly, freeing f within the function frees the local copy. Until C gains references, there are two possibilities. First pass a pointer to the pointer and use that:
void freeTouch (Touch **pF){
if (*pF != NULL){
free (*pF);
*pF = NULL;
}
}
:
freeTouch (&myTouch);
or pass back NULL so you can assign:
void *freeTouch (Touch *f){
free (f);
return NULL;
}
:
myTouch = freeTouch (myTouch);
You'll notice that the second one doesn't care whether you pass in NULL - it's perfectly acceptable to try an free the NULL pointer since it's effectively a no-op (other than the function call itself).
First of all, never use
x = realloc(x, size);
because if x is allocated before and realloc fails, you make it NULL while the memory is still there and therefore you create garbage.
Second,
void freeTouch(Touch *f);
gets a pointer by value and therefore cannot change the pointer itself. So your f = NULL; is not effective. You need to change your code to:
int main(){
Touch *myTouch = NULL, temp;
int inputCounter = 0;
//whenever a touch is recognized:
...
temp = realloc(myTouch,sizeof(*temp) * (inputCounter++));
if (temp == NULL)
/* handle error */
myTouch = temp;
...
// everything works fine until:
freeTouch(&myTouch);
}
void freeTouch(Touch **f){
if(f != NULL && *f != NULL){
free(*f);
*f = NULL;
}
}
Sidenote: It's a good idea to use realloc (and likewise malloc) like this:
x = realloc(count * sizeof(*x));
There is no need to cast the output or realloc. Also, sizeof(*x) allows you to not repeat the type of x every time.

segfault when allocate memory dynamically in C

I've been trying to build a priority queue in C.
First of all, I do some initialization work such as allocating space.
The following is the Initialize routine and PriorityQueue is a pointer.
void Initialize(int MaxElement, PriorityQueue H)
{
if (MaxElement < MinPQSize)
printf("Priority queue size is too small");
if (!(H = (PriorityQueue)malloc(sizeof(struct HeapStruct))))
printf("Out of space!!!");
if (!(H->Elements = (ElementType *)malloc((MaxElement+1) * sizeof(ElementType))))
printf("Out of space!!!");
H->Capacity = MaxElement;
H->Size = 0;
H->Elements[0] = MinData;
}
Here is how the test code is like
int MaxElement = 15;
PriorityQueue myHeap;
Initialize(MaxElement, myHeap);
But when I try to insert elements into the heap, a segmentation fault pops out.
It can be solved by simply returning the PriorityQueue pointer from Initialize routine.
PriorityQueue Initialize(int MaxElement, PriorityQueue H)
{
...
return H;
}
myHeap = Initialize(MaxElement, myHeap);
So what's happening under the hood?
Is free() invoked when the function returns without a return value?
Thx in advance!
No, even though the H that you're passing in is a pointer, you're trying to change it within the function (with your first malloc). In order to change something, you need to pass a pointer to it. In this case, that means a pointer to a pointer:
void Initialize (int MaxElem, PriorityQueue *H) {
if (MaxElem < MinPQSize)
printf("Priority queue size is too small");
if (!(*H = (PriorityQueue)malloc(sizeof(struct HeapStruct))))
printf("Out of space!!!");
if (!((*H)->Elements = (ElemType *)malloc((MaxElem+1) * sizeof(ElemType))))
printf("Out of space!!!");
(*H)->Capacity = MaxElem;
(*H)->Size = 0;
(*H)->Elements[0] = MinData;
}
Without the extra level on indirection, the H that you change within the function is isolated to the function - it is not reflected back to the caller.
A couple of other points you may want to consider:
You shouldn't cast the return from malloc, it can hide certain errors that you really do want to know about.
If your second malloc fails, you should free the result of the first malloc.
If either of your malloc calls fail, you should return rather than continue, since continuing will cause undefined behaviour if you dereference the null pointer.
You probably don't want to print things from general purpose functions since that's probably an unwanted behaviour. If you must indicate a problem, you're better off passing back an indication to the caller to let them handle it in their own way.
Although to be honest, I actually like the versions that return a value (with no need to pass it in beforehand since you're clearly creating a new thing). Something like this should do:
PriorityQueue Initialize (int MaxElem) {
PriorityQueue H;
if (MaxElem < MinPQSize) {
printf("Priority queue size is too small");
return NULL;
}
if (!(H = malloc(sizeof(*H)))) {
printf("Out of space!!!");
return NULL;
}
if (!(H->Elements = malloc((MaxElem+1) * sizeof(ElementType)))) {
printf("Out of space!!!");
free (H);
return NULL;
}
H->Capacity = MaxElem;
H->Size = 0;
H->Elements[0] = MinData;
return H;
}
PriorityQueue myHeap = Initialize (MaxElement);
You are passing the pointer by value, allow me to illustrate:
char* c = 0;
void set_c(char* ptr)
{
ptr = (char*) malloc(sizeof(char) * 10);
}
// a copy of c is sent in,
set_c(c);
// c doesn't point to the newly allocated data!
To set it correctly, you have to pass your pointer BY pointer, like this:
void set_c_correctly(char** ptr)
{
*ptr = (char*) malloc(sizeof(char) * 10);
}
// a pointer to c is passed in
set_c_correctly(&c);
// now c points to the newly allocated data

Resources