realloc(): invalid next size after two computations - c

I created the structure to store an array of digits. The array is dynamically allocated. The problem occurs when trying to reallocate some space in function. The error is
realloc(): invalid next size
Aborted (core dumped)
The structure is as follows
typedef struct big_number {
unsigned int *digits;
int num_of_digits;
}BigNumber;
The function looks like this (multiplies digit with BigNumber):
void scale(BigNumber a, int c, BigNumber* scaled)
{
scaled->num_of_digits = a.num_of_digits;
scaled->digits = NULL;
scaled->digits = malloc(scaled->num_of_digits * sizeof (unsigned int));
if (scaled->digits == NULL) {
error();
}
int carry = 0;
for (int i = scaled->num_of_digits; i >= 0; i--) {
int tmp = a.digits[i] * c + carry;
scaled->digits[i] = tmp % 10;
carry = tmp / 10;
}
if (carry != 0) {
//While trying realloc in this line problem occurs
scaled->num_of_digits += 1;
scaled->digits = realloc(scaled->digits, scaled->num_of_digits * sizeof (unsigned int));
scaled->digits[0] = carry;
}
}
The calls in main look like this:
printf("Results:\n");
scale(num_b, 5, &pomocna);
print_big_number(pomocna);
free(pomocna.digits);

Arrays go from 0 to n-1. You are writing to array[n] which does not exist
scaled->digits = malloc(scaled->num_of_digits * sizeof (unsigned int));
for (int i = scaled->num_of_digits; i >= 0; i--) { // AAA
int tmp = a.digits[i] * c + carry;
scaled->digits[i] = tmp % 10; // BBB
In line AAA you set i to the size of array (to n)
In line BBB you try to change scaled->digits[i] (array[n])

Related

I have an unexpected buffer overrun warning, why do I have that?

I have to create a function that sum components of a vector this way:
first + second,
third + fourth,
5th + 6th, and so on.
original vector has size "size".
I have to create a result vector dynamically with size "size/2", (because doing sum this way I've halved the original vector size).
I've used two counters, i and j, "i" is counter of the original vector, and "j" is counter of vector "result". I think the problem is here, because I have a buffer overrun warning.
this is my code:
#include <stdint.h>
#include <stdlib.h>
uint32_t* add_twobytwo(uint32_t* vect, size_t size) {
if (vect == NULL) {
return NULL;
}
uint32_t* result = malloc((size / 2) * sizeof(uint32_t));
if (result == NULL) {
return NULL;
}
size_t j = 0;
for (size_t i = 0; i < size; i += 2) {
result[j] = vect[i] + vect[i + 1];
j++;
}
return result;
}
int main(void)
{
size_t n = 6;
uint32_t* v = malloc(n * sizeof(uint32_t));
if (v == NULL) {
return NULL;
}
v[0] = 3; v[1] = 87; v[2] = 5; v[3] = 7; v[4] = 12; v[5] = 9;
uint32_t* sum = add_twobytwo(v, n);
free(v);
free(sum);
return 0;
}
green squiggle is located here:
for (size_t i = 0; i < size; i += 2) {
result[j] = vect[i] + vect[i + 1];
j++;
}
I've tried to interpret the warning, and it seems that there isn't enough space in result[], but it's working properly and it does its job correctly (I've debugged line-by-line to state this).
You get a warning, because if size were odd, then you would be reading elements past the end of vect. Imagine what would happen if size was 3:
At first, you have i=0,j=0;.
result[0] = vect[0]+vect[1];
j++. j is now 1.
i+=2;. i is now 2.
result[1] = vect[2]+vect[3];
However, because vect has a size of 3, trying to read vect[3] (which you are), will (most likely) produce a segmentation fault.

(C) malloc corrupted top size with random numbers

So I'm trying to get an array of random 8-bit numbers of size count but I get the corrupted top size error whenever count is larger than 6. I read that it should be related to memory assignment but I can't figure out what is wrong exactly. I'm new to C so I'm not sure if the pointers are written correctly.
int *randBytes(int count) {
srand(time(0));
int *num = calloc(count, sizeof(uint8_t));
for (int i = 0; i < count; i++) {
num[i] = (rand() % 255) + 1;
}
return num;
};
int main() {
int randLen = 120;
int *nums = randBytes(randLen);
for (int i = 0; i < randLen; i++) {
printf("%d ", nums[i]);
}
}
int *num = calloc(count, sizeof(uint8_t));
You are allocating a buffer of size count * 1 == count. If sizeof(int) == 4 then the array can contain count / 4 ints.
for (int i = 0; i < count; i++) {
num[i] = (rand() % 255) + 1;
}
You are then treating the array as an array of count ints, not count / 4 ints.
You can fix this by either changing your calloc:
int *num = calloc(count, sizeof(*num));
or your for loop:
for (int i = 0; i < count / sizeof(int); i++) {
num[i] = (rand() % 255) + 1;
}
It should be int *num = calloc(count, sizeof(int));
int *num = calloc(count, sizeof(uint8_t));
From the above line by doing a calloc you are a creating a memory of count bytes of type uint8_t and are using a int* to store and access the dynamically created memory.
And this happens to be the reason that you get corrupted data, when you dereference it to initialize each of the elements in an array you are dereferencing 4 bytes (32 bits) at a time, since the pointer is of the type int and not uint8_t that would dereference 1 byte(8 bits) as per your requirement. Say your array count is 10 , you do create an array of 10 bytes but the for loop that does the initialization end up accessing 40 bytes causing the data corruption and might end up causing a segmentation fault due to invalid memory access(due to accessing memory that was beyond the bounds of 10 bytes that you had created).
You can make the following changes to your code for it to work fine
uint8_t* randBytes(int count) {
srand(time(0));
uint8_t *num = calloc(count, sizeof(uint8_t));
for (int i = 0; i < count; i++) {
num[i] = (rand() % 255) + 1;
}
return num;
};
int main() {
int randLen = 120;
uint8_t *nums = randBytes(randLen);
for (int i = 0; i < randLen; i++) {
printf("%d ", nums[i]);
}
}

segmantation fault malloc pointers functions

hello guys this is my code :
#include <stdio.h>
#include <stdlib.h>
int power(int a, int b) {
int exponent = b, result = 1;
while (exponent != 0) {
result = result * a;
exponent--;
}
//printf("%d",result);
return result;
}
int fill_it(char ** p, int N, int fliptimes, int column2) {
if (N < 0) return 0;
int counter = 0, l;
char a = 'H';
for (l = 0; l < power(2, fliptimes); l++) {
p[l][column2] = a;
counter++;
if (counter == (power(2, N) / 2)) {
counter = 0;
if (a == 'H') a = 'T';
if (a == 'T') a = 'H';
}
}
fill_it(p, N--, fliptimes, column2++);
}
int main() {
int i, fores, j, l, m;
char ** p;
printf("how many times did you toss the coin?:");
scanf("%d", & fores);
p = (char ** ) malloc((power(2, fores)) * sizeof(char * ));
for (i = 0; i < fores; i++)
p[i] = (char * ) malloc(fores * sizeof(char));
fill_it(p, fores, fores, 0);
for (l = 0; l < power(2, fores); l++) {
for (m = 0; m < fores; m++) {
printf("%c", p[l][m]);
}
}
printf(",");
}
it does compile.But when i run the program it returns a "segmantation fault (core dumped)" error
i know it means that i tried to access memory,i dont have acces to but i dont understand which part of the program is defective
The problem is, you're not allocating enough memory. This line is fine
p = (char ** ) malloc((power(2, fores)) * sizeof(char * ));
but this loop is only allocating memory for part of the 2-dimensional array.
for (i = 0; i < fores; i++)
p[i] = (char * ) malloc(fores * sizeof(char));
The memory allocation should look more like this...
foresSquared = power(2, fores);
p = malloc(foresSquared*sizeof(char *));
for (i = 0; i < foresSquared; i++)
p[i] = malloc(fores);
Since the result of power is going to be consistent, it makes sense to store the value in a variable and use that rather than recalculating it. It'll make the code clearer too.
You also don't need to cast the return value of malloc as C handles that for you. And sizeof(char) isn't needed as it's guaranteed to always be 1.

Given an array of single digit, positive integers, convert to a whole number, multiply by 2, return an array of new product with each digit in array

For example:
[1,2,3] -> [2,4,6]
[9,1] -> [1,8,2]
[6,7,5] -> [1,3,5,0]
I got this question on my first tech interview yesterday (did it in C because that's my best language, so a C answer would be help more) and completely blanked :(
This is what I was thinking:
Start at the end of the array and keeping moving left
At every arr[i], multiply by 2 and see if there're 2 digits (if arr[i]/10 != 0) and if there is a left most digit, carry it over to arr[i-1] as long as a[i-1] != NULL.
I just could not figure out how to actually do this in C. I had something like:
int* multTwo(int* arr, int len) {
int *newarr; // I know i have to malloc, but not sure what size because
// wouldnt the size depend on the new number's size?
int temp, i;
for (i=len-1; i>=0; i--) {
temp = arr[i]*2;
newarr[i] = temp%2;
if(temp/10 != 0)
newarr[i-1] = temp/2;
}
return newarr;
}
But there are a lot of bugs in my code. Is there a better way or am I on the right track?
Some pseudo code. The main idea is to show the depth of C knowledge as part of the interview, not Code golf.
What signature?
// arr is not changed, use `const`
// array indexing best done with `size_t`
int* multTwo(const int* arr, size_t len) {
Size needed and show error handling. Maybe also detect arr == NULL when len > 0
need = len;
// if lead element is 5 or more, add 1.
// Error if element is not in 0-9 range
Allocate memory. Allocating to size of variable de-referenced type is less error prone, easier to review and maintain than coding the variable type. Showing maintenance concerns during a C interview is a good thing. Think if later code changed to unsigned char* multTwo(const unsigned char* arr, size_t len) {, no need to change newarr = malloc(sizeof *newarr * need).
newarr = malloc(sizeof *newarr * need)
Check allocation. An allocation of 0 is OK to return NULL. Yet maybe this routine should still allocate 1 byte, a tad wasteful, to insure a NULL return is an error. Discussing issues like with the interviewer is good. Shows you want to clearly understand the customer's need not just in the meat of the function, but the corner cases.
if (newarr == NULL && need > 0) fail()
Loop though and populate the new array much like OP coded with meaningful variable names and using unsigned array indexing.
size_t arr_i=len;
size_t newarr_i=need;
int carry = 0;
while (arr_i > 0)
sum = arr[--arr_i]*2 + carry;
newarr[--newarr_i] = sum%10;
carry = sum/10;
}
if (carry) {
newarr[--newarr_i] = carry;
}
Return newarr
Best I can think in a short time, like an interview
#include <stdio.h>
#include <stdlib.h>
void invert (int *head, int *tail)
{
int temp;
if (head < tail)
{
temp = *head;
*head = *tail;
*tail = temp;
invert(++head, --tail);
}
}
int* multTwo(int* arr, size_t len)
{
int value = 0;
int n_digits =0 ;
// CONVERT THE ARRAY TO NUMBER
while(len--)
{
value += *arr;
value *=10;
arr++;
}
value /= 10;
// DOUBLE THE NUMBER
value *= 2;
// CONVERT IT TO BUFFER
int *digits = malloc(sizeof(*digits));
while ((value>0) && (digits != NULL))
{
digits[n_digits++] = value%10;
value /= 10;
digits = realloc( digits, sizeof(*digits) * (n_digits+1) );
}
if (digits != NULL)
{
invert(digits, &digits[n_digits-1]);
printf("[ ");
for (int i=0; i<n_digits; i++)
printf("%d, ", digits[i]);
printf("]\n");
}
return digits;
}
int main(void)
{
int array[] = {6,7,5};
multTwo(array, sizeof(array)/sizeof(array[0]));
return 0;
}
I would start by looking to see if either the first digit in arr is 5 or more to check if the newarr array needs to be 1 larger than the original array.
So something like this for initialization:
int* newarr;
int newlen;
if (*arr >= 5)
newlen = len + 1;
else
newlen = len;
newarr = (int*)malloc(sizeof(int) * newlen);
memset(newarr, 0, newlen); //initialize all newarr values to 0
Now obviously we have to do our multiplication now. To get the 1's digit we do use the modulo operator %, and to get the 10's digit we use the division operator /. Of course we only need to do the division if our multiplied value is 10 or greater. So our loop to populate newarr will look something like this:
int i, temp;
for (i = 1; i <= len; i++) {
temp = *(arr + i - 1) * 2;
if (temp < 10) {
*(newarr + i - 1) += temp;
}
else {
*(newarr + i - 1) += temp / 10; //inset 10's digit
*(newarr + i) += temp % 10; //inset 1's digit
}
}
So our full function ends up being
#include <stdlib.h>
#include <string.h>
int* multTwo(int* arr, int len)
{
int* newarr;
int newlen;
if (*arr >= 5)
newlen = len + 1;
else
newlen = len;
newarr = (int*)malloc(sizeof(int) * newlen);
memset(newarr, 0, newlen); //initialize all newarr values to 0
int i, temp;
for (i = 1; i <= len; i++) {
temp = *(arr + i - 1) * 2;
if (temp < 10) {
*(newarr + i - 1) += temp;
}
else {
*(newarr + i - 1) += temp / 10; //insert 10's digit
*(newarr + i) += temp % 10; //inset 1's digit
}
}
return newarr; //don't forget to free once you're done with newarr!
}

Issue with custom malloc implementation

I am working on a custom malloc and free implementation in C. My code works fine, but not perfectly. In my file that tests my_malloc and my_free, I call my_malloc 3 times. It works for the first 2 calls, but doesn't for the 3rd call. Everything is exactly the same, so I really have no idea why it wouldn't work again. I know there's enough memory in the heap, so it's not that. It even works to the point of returning an address for the pointer variable, but the test file won't write to it.
Here's the bit of code to test my_malloc and my_free, it breaks with c:
static int *base;
static int *heap_end;
int total_mem_used = 0;
int first_call = 1;
int i;
int *a, *b, *c;
if ((a=(int *)my_malloc(10))==NULL)
return MALLOC_FAIL;
for (i=0;i<10;i++)
a[i] = i;
for (i=0;i<10;i++)
printf("%d\n", a[i]);
if ((b=(int *)my_malloc(18))==NULL)
return MALLOC_FAIL;
for (i=0;i<18;i++)
b[i] = i*i;
for (i = 0; i < 18; i++)
printf("%d ", b[i]);
printf("\n");
if ((c=(int *)my_malloc(5))==NULL)
return MALLOC_FAIL;
for (i=0;i<5;i++)
c[i] = i*7;
Here's my_malloc too, if it helps:
void *p;
int *t;
int data_size, block;
if (size==0)
return NULL;
if (first_call) {
if ((base=(int *)malloc(HEAP_SIZE))==NULL)
return NULL;
init_heap(norm_size(size)+8);
heap_end = &base[HEAP_SIZE];
first_call = 0;
total_mem_used += (norm_size(size)+2);
t = base;
return (void *) (t+2);
}
data_size = norm_size(size);
block = data_size + 2;
p = find_first_free(block);
if (p==0) {
errno = ENOMEM;
return NULL;
}
total_mem_used += block;
fill_header((int *) p, block);
t = (int *) p + 2;
return (void *) t;
void my_free(void *p) {
int *t;
t = (int *) p - 2;
*t = *t & -2;
coalesce(t);
}
void *find_first_free(int n) {
int *p;
p = base;
while (p<heap_end && ((*p & 1) || (*p <= n)))
p = p + (*p & -2);
return (void *)p;
}
int norm_size(int w) {
if (w % 8 == 0)
return w;
else
return w + (8 - w % 8);
}
void init_heap(int n) {
base[0] = n+1; // n+1 since we're allocating it
base[1] = (int) &base[n];
base[n-1] = n+1;
base[n] = HEAP_SIZE - n;
base[HEAP_SIZE-1] = HEAP_SIZE - n;
}
void fill_header(int *p, int w) {
p[0] = w+1;
p[1] = (int) &p[w];
p[w-1] = w+1;
p[w] = HEAP_SIZE - total_mem_used;
p[w+HEAP_SIZE-total_mem_used-1] = HEAP_SIZE - total_mem_used;
}
Any idea what exactly is wrong with the program? Thanks for any help.
Avoid magic numbers
block = data_size + 2;
Why 2? why not 16 or 256? Certainly the addition is done to provide for saving the size. In that case, add the size of the int.
block = data_size + sizeof(int);
t = (int *) p + 2;
Why 2 versus any other number? Again, this is done to account for the size begin saved at p. But this is not integer addition like before. This is "pointer addition". With + 2, p is increased by the 2 * sizeof(int). Likely code should be
t = p + 1;
This is an exception to the "no magic numbers" rule: -1,0,+1 are OK
To answer more, post complete functions.
Minor: cast not needed
// if ((base=(int *)malloc(HEAP_SIZE))==NULL)
if ((base = malloc(HEAP_SIZE)) == NULL)
Minor: Consider the unsigned type size_t. That is the type returned by functions/operators like strlen(), sizeof()
// int data_size
size_t data_size
// if ((a=(int *)my_malloc(10))==NULL)
a = my_malloc(10);
if (a == NULL)
Why 8 in init_heap(norm_size(size)+8);? Use a constant/define
#define MY_MALLOC_GUARD (8)
init_heap(norm_size(size) + MY_MALLOC_GUARD);

Resources