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

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.

Related

How to generate an array of a specific value with given input array in C code

The title may be a little confusing so I will explain my goal a bit more in detail here;
I want to write a code that takes an input array of the x numbers
index_x = [0,0,1,0,1,0,0,0,1,0,0,1,0];
Then I want to write a logic that will generate an array that has the index of all the 1s
index_ones = [3,5,9,12];
Current code slightly modified from Jacon:
Edit 1:
#include <stdio.h>
int index_x[] = {0,0,1,0,1,0,0,0,1,0,0,1,0}; // any number of elements
int len = 12;
int main(void) {
int arr[len];
int j = 0;
for (int i = 0; i < len; i++)
if (index_x[i])
arr[j++] = i; // save and advance j only if value is "1"
for (int i = 0; i < j; i++) // only print below j !
printf("%d\n", arr[i]);
}
Output:
2
4
8
11
From this output, I would like to generate another array that is the difference between these elements. In this case the new array would be {2,4,3}.
Edit 2: I will move this to another thread as the discussion has now moved from one problem to another. Do not want to complicate things for future users.
As you do not know how many indexes you need you will need to allocate the memory dynamically. You need also to remember the number of indexes
struct index
{
size_t size;
size_t indexes[];
};
struct index *addIndex(struct index *index, size_t pos)
{
size_t new_size = index ? index -> size + 1 : 1;
index = realloc(index, sizeof(*index) + new_size * sizeof(index -> indexes[0]));
if(index)
{
index -> size = new_size;
index -> indexes[new_size - 1] = pos;
}
return index;
}
struct index *buildIndex(int *arr, size_t arr_size, int val)
{
struct index *index = NULL, *tmp;
for(size_t pos = 0; pos < arr_size; pos++)
{
if(arr[pos] == val)
{
tmp = addIndex(index, pos);
if(tmp) index = tmp;
else { /* error handling */ }
}
}
return index;
}
Find array element count of index_x[].
int index_x[] = {0,0,1,0,1,0,0,0,1,0,0,1,0};
...
// e.g. 13, not 12 as implied with int len = 12;
size_t index_x_count = sizeof index_x / sizeof index_x[0];
Then run through index_x[] to find numbers of the ones.
size_t ones = 0;
for (size_t i = 0; i < index_x_count; i++) {
if (index_x[i] == 1) {
ones++;
}
}
Now we know the size needed for "generate an array that has the index of all the 1s"
// Error check, can't have array size 0
if (ones == 0) Handle_patholocial_case();
// We should avoid forming huge arrays. 10000 is arbitrary.
// When large, rather than form _arrays_, allocate memory (not shown).
if (ones > 10000) Handle_patholocial_case();
// Form the array
int arr[ones];
size_t a = 0;
for (size_t i = 0; i < ones; i++) {
if (index_x[i] == 1) {
arr[a++] = i;
}
}
generate another array that is the difference between these elements.
// Error check for at least one difference, can't have array size 0
if (ones <= 1) Handle_patholocial_case();
// Form the array
size_t diff_count = ones - 1;
int diff[diff_count];
for (size_t d = 0; d < diff_count; d++) {
diff[a] = arr[d+1] - arr[d];
}
Do something with diff[]
for (size_t d = 0; d < diff_count; d++) {
printf("%d ", diff[d]);
}

Multiply a digit array by int in C

I have a very large number (>100 digits long) so it can't be stored as an int or even an unsigned long long (aka uint64_t). The array looks like this:
{5, 1, 2 ... 8, 6}
The array must contain single digit ints.
Question
What would be a simple, and most importantly efficient, way of multiplying this 'number' (keeping it as an array) by a single digit?
What I have tried
As I am fairly new to C, this code is not a masterpiece. Far from it.
struct returnpointer { int * pointer; int length; };
returnpointer mul_arrays(int * x, int y, int lengthof_x) {
returnpointer result_end;
int result[lengthof_x * 2 + 1];
int final_result[lengthof_x * 2 + 1];
int carry = 0;
int j = 0;
//multiply 'y' by all digits of x, which creates multidigit ints
//and also reverses the direction of the array (to allow carrying)
for (int i = lengthof_x; i >= 0; i--) {
result[j] = x[i] * y;
j++;
}
int i = 0;
j = lengthof_x
//this is the bit that doesn't work: it attempts to work out the carry
//however after hours of debugging I can't get it to work.
while (carry > 0 || i < lengthof_x + 1) {
if (result[j] > 9) {
carry = result[j] / 10;
final_result[i] = result[j] % 10;
final_result[i + 1] = carry;
} else {
final_result[i] = result[j];
carry = 0;
}
i++;
j--;
}
result_end.pointer = result;
result_end.length = i + 1;
return result_end;
}
This code does not work properly. It is just an illustration of what I have tried (if it worked I would not be posting this).
In addition, it would be nice to know if the approach I am (trying to) use is the most efficient, as the program it will be incorporated into is very time-intensive so the faster the function the less time the entire program will take.
Thanks in advance.
EDIT:
My compiler is g++.
As requested, here is a code example that multiplies an array by a single digit. The array is little-endian. For a simple example, I have assumed that the array is of fixed length, a more complex one would allocate array memory and extend it if the array grows too big.
#include <stdio.h>
#define BIGLEN 20
typedef struct {
int length;
int array[BIGLEN];
} biggy_t;
void bigmul(biggy_t *big, int mul)
{
int carry = 0, partial;
for(int i = 0; i < big->length; i++) {
partial = big->array[i] * mul + carry;
big->array[i] = partial % 10;
carry = partial / 10;
}
if(carry) {
big->array[big->length] = carry;
big->length++;
}
}
void bigout(biggy_t *big)
{
for(int i = big->length-1; i >= 0; i--) {
printf("%d", big->array[i]);
}
}
int main(int argc, char *argv[])
{
biggy_t big = { 6, { 5, 1, 2, 3, 8, 6 }}; // reverse order
bigout(&big);
printf(" * 7 = ");
bigmul(&big, 7);
bigout(&big);
printf("\n");
}
Program output
683215 * 7 = 4782505
I wrote a bignum implementation in which I can chose the radix. 10 or 100 for byte storage, much more for 32-bit storage. Sticking to a power of 10 makes the conversion to decimal output easier than a power of 2 radix, with a small time penalty for not using the full capacity of the storage type.
So a few observations:
1) I don't think there is any need to reverse the array. Just process it from least significant to most significant digit.
2) There is no reason to store temporary values larger than your allowable digit range. Just do the carry as you go, like you would if you were doing it by hand:
carry = 0
for i in all_the_digits:
product = x[i]*y + carry
x[i] = product%10
carry = product/10
3) you can store the digits as uint8_t without fear of overflow - this will make your array 1/4 the current size, which should improve speed due to caching effects.
There are multiple problems in your code. Not sure I have spotted all of them but here is some to start with.
This loop:
for (int i = lengthof_x; i >= 0; i--) {
result[j] = x[i] * y;
j++;
}
execute "lengthof_x + 1" times. In other words - one time too many! You want to change it to:
for (int i = lengthof_x - 1; i >= 0; i--) { // notice the "- 1"
result[j] = x[i] * y;
j++;
}
Further you have:
result_end.pointer = result;
but it seems that you have calculated the result in the variable final_result so you are returning the wrong array.
However - in any case you are not allowed to return a pointer to a local array! It will go out of scope when the function returns. So even if you do:
result_end.pointer = final_result;
it is still invalid code. You'll need to malloc the array (and that will hurt performance).
Then you have:
result_end.length = i + 1;
So you increment the length in all cases. That's wrong. You should only increment when you have a carry.
Below I have tried to fix your code, i.e. I have tried to keep the overall structure of your code so that you can see where you did mistakes.
#include <stdio.h>
#include <stdlib.h>
struct returnpointer { int * pointer; int length; };
void print_num(struct returnpointer * num)
{
printf("len=%d\nvalue=", num->length);
for(int i = 0; i <num->length; i++) {
printf("%d", num->pointer[i]);
}
}
struct returnpointer mul_arrays(int * x, int y, int lengthof_x) {
struct returnpointer result_end;
int result[lengthof_x + 1];
// Multiply all element and revert array
int j = 0;
for (int i = lengthof_x-1; i >= 0; i--) {
result[j] = x[i] * y;
j++;
}
// Handle carry
int carry = 0;
for (j = 0; j < lengthof_x; j++) {
result[j] = result[j] + carry;
carry = result[j] / 10;
result[j] = result[j] % 10;
}
// Did length increase
if (carry)
{
lengthof_x++;
result[j] = carry;
}
// malloc result and revert back to desired format
j = 0;
int* final_result = malloc(lengthof_x * sizeof *final_result);
for (int i = lengthof_x-1; i >= 0; i--) {
final_result[j] = result[i];
j++;
}
result_end.pointer = final_result;
result_end.length = lengthof_x;
return result_end;
}
int main(int argc, char *argv[])
{
int arr[] = { 5, 1, 2, 3, 8, 6};
struct returnpointer num = mul_arrays(arr, 2, 6); // 512386 * 2 -> 1024772
print_num(&num);
}
Output:
len=7
value=1024772
Notice however that this is not an optimal solution...

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