I have a program that takes as input an integer n followed by (n+1) lists. The integers in these lists are used to perform an arbitrary mathematical operation. Input will look like this for example:
5
2: [2,-2]
3: [1,-1,1]
4: [-5,3,-5,-1]
5: [2,-1,-1,-5,-2]
6: [-5,4,-3,3,4,-3]
10: [-23,9,-15,-22,5,6,-21,-15,-22,4]
The desired output is:
25: [-2300,9870,-23594,42570,-55674,58618,-44668,17698,7396,-18046,4346,25258,-50964,54140,-34960,3790,14120,-19116,16540,-9380,4494,1702,-1824,-64,48]
The way I read these lists is that I perform the operation as I read. In other words, I read a line and then perform an operation and then read the next line instead of reading every line and then performing the operation all in one go.
h_init is the array I use to "accumulate" my intermediate results in.
h_next is used to store the next list that is read.
temp is to store the calculated results within each iteration of the for loop.
At the end of each iteration I will copy temp into h_init.
After the mathematical operation is performed, the length of the result increases therefore I use realloc to extend the length of h_init at the end of every iteration.
When I run my code with input I get the following error:
malloc: Incorrect checksum for freed object 0x7fae81505280: probably modified after being freed.
Corrupt value: 0xffffffea0000000c
So I understand that this error is saying that my error is most likely trying to access an array after I've freed it but I don't understand how and where this is happening. In my code you can see that I instantiate h_next and temp at the very start of the for loop and then I free them both just before the current iteration ends.
So my question is: where am I supposed to free temp and h_next then to avoid this error?
(See code below)
void *safeMalloc(int sz) {
void *p = calloc(sz, 1);
if (p == NULL) {
fprintf(stderr, "Fatal error: safeMalloc(%d) failed.\n", sz);
exit(EXIT_FAILURE);
}
return p;
}
int *makeIntArray(int n) {
/* allocates dynamic int array of size/length n */
return safeMalloc(n*sizeof(int));
}
void printIntArray(int length, int *arr) {
printf("[");
if (length > 0) {
printf("%d", arr[0]);
for (int i=1; i<length; i++) {
printf(",%d", arr[i]);
}
}
printf("]\n");
}
int *readSignal(int *len) {
int *x;
char c;
scanf("%d:", len);
x = calloc(*len, sizeof(int));
do c = getchar(); while (c != '[');
if (*len > 0) {
scanf("%d", &x[0]);
for (int i=1; i < *len; i++) scanf(",%d", &x[i]);
}
do c = getchar(); while (c != ']');
return x;
}
void printSignal(int len, int *x) {
printf("%d: [", len);
if (len > 0) {
printf("%d", x[0]);
for (int i=1; i < len; i++) printf(",%d", x[i]);
}
printf("]\n");
}
int main(int argc, char *argv[]) {
int n;
scanf("%d\n", &n);
int len_h_init;
int *h_init;
h_init = readSignal(&len_h_init);
for (int i = 0; i < n; i++){
int len_next;
int *h_next;
int len_temp;
int *temp;
h_next=readSignal(&len_next);
int temp_indent = 0;
len_temp = (len_h_init-1) + len_next;
temp = makeIntArray(len_temp);
for(int i=0; i<len_h_init; i++){
for(int j=0; j<len_next; j++){
temp[temp_indent+j] = temp[temp_indent+j] + h_init[i]*h_next[j];
}
temp_indent = temp_indent + 1;
}
h_init = (int *) realloc(h_init, len_temp);
len_h_init = len_temp;
for(int z = 0; z < len_h_init; z++) {
h_init[z] = temp[z];
}
free(temp);
free(h_next);
}
printSignal(len_h_init, h_init);
return 0;
}
AddressSanitizer showed me that I was getting a heap buffer overflow error. I tried to fix it by freeing h_init before using realloc and that fixed the problem.
Related
Hello I am trying to print something like this with 2d array.
Note that when user enters the same number, character should be printed above existing char.
EXPECTED RESULTS:
Input 1: 3 //user1 inputs 3
****
****
**x*
Input 2: 1 //user2 inputs 1
****
****
y*x*
Input 3: 1 //user1 inputs 1
****
x***
y*x*
current results:
enter first: 3
3***
***
**x
enter second: 1
1******
******
xx****
enter first: 2
2*********
*********
***xxx***
But keeping printed values on its previous places.
The problem is that they don't get printed in right order. And also it seems that I haven't done the best job with 2d array which is dynamically allocated.
Here is something what I've tried:
#include <stdio.h>
#include <stdlib.h>
int num(int term)
{
int number1;
int number2;
if(term==1)
{
scanf("%d", &number1);
return number1;
}
if (term==2)
{
scanf("%d", &number2);
return number2;
}
return 0;
}
void function(int a, int b, int result[], int size)
{
int i = 0;
int j = 0;
int desired_num = 0;
int count = 0;
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
for (i = 0; i < a; i++)
for (j = 0; j < b; j++)
arr[i][j] = ++count;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
{
arr[i][j] = desired_num;
}
if (arr[i][j] == desired_num)
{
printf("%s", "x");
}
else
{
printf("*");
}
}
}
printf("\n");
}
}
int main()
{
int counter = 1;
int i = 0;
int given_number;
int array[20];
for (;;)
{
if (counter % 2 != 0)
{
printf("enter first: ");
given_number = num(1);
printf("%d", given_number);
}
else
{
printf("enter second: ");
given_number = num(2);
printf("%d", given_number);
}
array[i] = given_number;
function(3, 3, array, counter);
counter++;
}
return 0;
}
array[i] = given_number;
i is never changed from the value of 0. You are only ever overwriting the first element of array each iteration. The other 19 elements remain in an indeterminate state.
counter and array are passed to function, as size and result respectively:
This means as size is incremented, it is used as a bounds for accessing elements of result; elements that contain indeterminate values.
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
This will surely lead to Undefined Behaviour as those indeterminate values are used to index arr, effectively accessing random memory offsets. This fact alone makes it hard to reason about the output you are seeing, as really anything is valid.
While perfectly valid, the variable-length array of dynamic allocations is a somewhat perplexing choice, especially considering you fail to free the memory allocated by malloc when you are done with it.
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
int arr[a][b]; would work, given a and b are not stack-crushingly large values (or non-positive). You are, or would be, bounded by the size of array in main anyway.
The triply nested loop is confused at best. There is only logic for printing the x and * characters, so you obviously will never see a y.
For each element of arr, you iterate through each element of result. If the current element of arr equals the value of the column selected by the current value of result ([result[counter] - 1]) in the last row (arr[a - 1]) you print x, otherwise *.
Again UB from utilizing indeterminate values of result, but you can see you are printing a * b * size characters, plus newlines, each iteration.
This is severely flawed.
Some other things of note:
The two branches of the if .. else statement in the num function do the exact same thing, just with different identifiers.
The two branches of the if .. else statement in main are identical, other than the first printf in each, and the integer value passed to num, which have the same effect.
This means the only thing that needs to branch is the printf argument.
A generic function for getting an integer would work fine
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
for use inside main
if (counter % 2 == 0)
printf("enter first: ");
else
printf("enter second: ");
given_number = get_num();
A small issue: printf("%d", given_number); is muddling the output slightly.
There is no reason to repeatedly generate the array. Initialize an array in main to serve as the state of the program. Over time, fill it with the users' selections, and simply print the array each iteration.
Make sure to always check the return value of scanf is the expected number of conversions, and ensure the integers provided by the users will not access invalid memory.
Here is a cursory example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY '*'
#define PLAYER_ONE 'X'
#define PLAYER_TWO 'O'
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
int main(void)
{
const size_t rows = 6;
const size_t cols = 7;
char board[rows][cols + 1];
memset(board, EMPTY, sizeof board);
/* our rows are now strings */
for (size_t i = 0; i < rows; i++) {
board[i][cols] = '\0';
puts(board[i]);
}
unsigned char turn = 1;
while (1) {
printf("Player %s, Enter column #(1-%zu): ",
turn & 1 ? "One" : "Two", rows);
int input = get_num();
if (1 > input || input > cols) {
printf("Invalid column [%d]. Try again...\n", input);
continue;
}
size_t sel = input - 1;
if (board[0][sel] != EMPTY) {
printf("Column [%d] is full! Try again...\n", input);
continue;
}
size_t n = rows;
while (n--) {
if (board[n][sel] == EMPTY) {
board[n][sel] = turn & 1 ? PLAYER_ONE : PLAYER_TWO;
break;
}
}
for (size_t i = 0; i < rows; i++)
puts(board[i]);
turn ^= 1
}
}
I am new to threads and I have a program that uses threads to find the minimum number out of a 2d array and later on, it finds the distance that the other elements of the array have from the minimum number and stores them in another array.
The user should enter the size of the array and the number of threads he wants to use.
I tried the program below for 1d array and it worked just fine. When I converted it to work for a 2d array it started crashing and throwing a segmentation fault. I, however, cannot find which part of the 2d declaration is wrong.
Any help is really appreciated.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
struct Parameters
{
// input
int s,p; //n is size of array, p is number of threads
int** array; //array with elements
int start;
int end;
// output
int smallest;
int pos; //position if minimum
int** B; //array that holds the distances
};
void* min(void* args)
{
struct Parameters* p = (struct Parameters*)args;
int **array = p->array;
int **B1 = p->B;
int start = p->start;
int end = p->end;
int smallest = array[start][start];
int pos = p->pos;
int distance;
//find the smallest
for (int i = start; i < end; i++)
{
for(int j = start; j < end; j++)
{
if (array[i][j] < smallest)
{
smallest = array[i][j];
pos = i;
}
}
}
//find the distances
for(int i = 0; i < ((struct Parameters*)args) -> s; i++)
{
for(int j = 0; j < ((struct Parameters*)args) -> s; j++)
{
distance = abs(pos - i);
B1[i][j] = distance;
}
}
params->smallest = smallest;
params->B = B1;
return NULL;
}
int main()
{
int smallest,pos;
int s,p;
struct Parameters *ptr = (struct Parameters *)malloc(sizeof(struct Parameters));
if(ptr == NULL)
{
printf("Not enough. Try again \n");
exit(0);
}
printf("Type s\n");
scanf("%d",&(ptr->s));
printf("Type p\n");
scanf("%d", &(ptr->p));
// declare an array of threads and associated parameter instances
pthread_t threads[(ptr->p)];
struct Parameters thread_parameters[(ptr->p)] ;
int arr[ptr->s][ptr->s];
int B2[ptr->s][ptr->s];
// intialize the array
for(int i=0; i< ptr->s; i++)
{
for(int j=0; j< ptr->s; j++)
{
printf("Type a \n");
scanf("%d",&arr[i][j]);
}
}
// smallest needs to be set to something
smallest = arr[0][0];
// start all the threads
for (int i = 0; i < ptr->p; i++)
{
memcpy(arr, thread_parameters[i].array, sizeof(arr));
thread_parameters[i].s = ptr->s;
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
thread_parameters[i].start = i * (ptr->s / ptr->p);
thread_parameters[i].end = (i+1) * (ptr->s / ptr->p);
pthread_create(&threads[i], NULL, min, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < ptr->p; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < ptr->p; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
}
printf("Smallest is %d\n", smallest);
thread_parameters[ptr->p].B[ptr->s][ptr->s];
for (int i = 0; i < 1; i++)
{
for(int j = 0; j < ptr->s;j++)
{
for(int k = 0; k < ptr->s; k++)
{
printf("Element %d is %d away from min\n",j,thread_parameters[i].B[j][k]);
}
}
}
return 0;
}
Thank you!!
The issue with your code might also come from :
memcpy(arr, thread_parameters[i].array, sizeof(arr));
...
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
as thread_parameters[i].array and thread_parameters[i].B are not allocated, if you are only reading the array it might b fine to only pass them by address
thread_parameters[i].array = arr
but for thread_parameters[i].B you would need to allocate the arrays and perform a deep copy (memcpy would not work)
The below text does not answer the question but does provide some insight on VLA usage
One reason for causing the segmentation with a declaration of a Variable Length Array is that the value is to large to allocate the array on the stack (some compiler choose this option, this choice might have performance reason).
The is not much option to recover cleanly from failure to allocate memory on the stack as there is little way to clean up stack memory during runtime within the same stack context.
You can mitigate the issue by allocating your 2D arrays on the heap instead, some of the strategies are available here(thanks #Lundin) and here.
int** alloc_2d_int_array(size_t rows, size_t cols) {
int **result = malloc(rows * sizeof(int *));
if(result == NULL) {
// could not allocate more memory
return NULL;
}
size_t row_size = cols * sizeof(int);
for(int i=0; i < rows; ++i) {
result[i] = malloc(row_size);
if(result[i] == NULL) {
// could not allocate more memory
// cleanup
return NULL;
}
}
return result;
}
the above implementation have not been tested, but does compile, there are still risk of integer overflow.
Then use the above define function as following:
int **arr = alloc_2d_int_array(ptr->s, ptr->s);
int **B2 = alloc_2d_int_array(ptr->s, ptr->s);
easier implementation (see here(thanks #Lundin))
int **arr = malloc(sizeof(int[ptr->s][ptr->s]);
int **B2 = malloc(sizeof(int[ptr->s][ptr->s]);
I created a struct, called ArrayCount, that contains a double array and an integer that should count how often an array occurs.
If the size of the double-array is n, the idea is, to create an array of the struct ArrayCount of the size n! (n! is called m in my code).
The idea is to safe each permutation in the ArrayCount-array, counting the occurrences of each permutation, for a given algorithm. But that's just the background information and not part of the problem.
I am having issues while freeing the memory that was allocated for the double-Arrays.
Oddly enough, ~ 1/10 times my code compiles without an error message and sometimes different error messages appear.
error message:
munmap_chunk(): invalid pointer
Aborted (core dumped)
error message:
free(): invalid size
Aborted (core dumped)
error message:
Segmentation fault (core dumped)
Part of the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double* array_copy(const double* a, int n) {
srand(time(NULL));
double* copy = calloc(n, 8);
for(int i = 0; i < n; i++) {
copy[i] = a[i];
}
return copy;
}
void shuffle(double* a, int n) {
for(int i = n - 1; i >= 0; i--) {
time_t t;
/* Intializes random number generator */
srand((unsigned) time(&t));
double* copy = array_copy(a, i + 1);
//Generates random numbers in the closed intervall [0,i].
int random = rand() % (i + 1);
a[i] = a[random];
a[random] = copy[i];
free(copy);
}
}
// Refers to a double array and counts how often this array has
occurred yet.
typedef struct {
double* array;
int counter;
} ArrayCount;
// Computes the factorial of n: n!.
int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
/*
Saves all permutations in array_counts, for a given double array of
the length n and counts how often each permutations occurs.
(Hint given by our supervisor: Save a copy of a in array_counts)
*/
void update_array_counts(/*INOUT*/ ArrayCount* array_counts, int m,
/*IN*/ const double* a, int n) {
double* copy_a = array_copy(a, n);
//Increases the counter by 1, if a is already listed in
array_counts
for(int i = 1; i <= m; i++) {
int count = 0;
for(int j = 0; j < n; j++) {
if(array_counts[i].array[j] == a[j]) count++;
}
if(count == n) {
array_counts[i].counter++;
free(copy_a);
return;
}
}
//Saves a in array_counts and sets the counter to 1, if a is not
listed in array_counts, yet
for(int i = 1; i <= m; i++) {
int count = 0;
for(int j = 0; j < n; j++) {
if(array_counts[i].array[j] == 0) count++;
}
if(count == n) {
for(int j = 0; j < n; j++) {
array_counts[i].array[j] = a[j];
}
array_counts[i].counter = 1;
free(copy_a);
return;
}
}
}
// Gibt die Häufigkeit der verschiedenen Permutationen eines Arrays
der Länge n aus.
void shuffle_frequency(int n) {
double a[n];
for (int i = 0; i < n; i++) {
a[i] = i;
}
int m = factorial(n);
ArrayCount* array_counts = calloc(m, sizeof(ArrayCount));
for(int i = 1; i <= m; i++){
array_counts[i].array = calloc(n, sizeof(double));
}
for (int i = 0; i < 1000 * m; i++) {
shuffle(a, n);
update_array_counts(array_counts, m, a, n);
}
for (int i = 1; i <= m; i++) {
printf("%4d%8d ", i, array_counts[i].counter);
}
//The next free-statement is causing problems.
for(int i = 1; i <= m; i++) {
printf("i = %d\n", i);
free(array_counts[i].array);
}
free(array_counts);
}
int main(void) {
shuffle_frequency(4);
return 0;
}
What am I doing wrong?
I am having issues while freeing the memory that was allocated for the
double-Arrays. Oddly enough, ~ 1/10 times my code compiles without an
error message and sometimes different error messages appear.
complies without error message or runs without error message? I see runtime errors ( Segfault or Abort signals, to be exact ) not compile time. kl
for (int i = 1; i <= m; i++) {
The correct way to iterate through an array of m elements is
for(int i=0; i < m; i++){
As pointed out in the comments, offsets start at 0 and to to m-1, not m. That makes free(array_counts[i].array) becomes free(array_counts[m].array) What's at array_counts[m]? Could be various things, which might be deterministic or nondeterministic at runtime, but it is outside the memory you allocated. Behavior of free is undefined in this case, as it is whenever passed an address that wasn't allocated with malloc and friends.
Consider http://man7.org/linux/man-pages/man3/malloc.3.html, a copy of the manpage for free:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc(), or
realloc(). Otherwise, or if free(ptr) has already been called
before, undefined behavior occurs.
I am trying to practice with C by making a bubble sort program. The problem until now seems to be that the for loop that is giving values to the cells of the array is stuck after the condition is no longer fulfilled but it doesn't seem to be executing the commands in the loop. I don't know what is happening exactly and I have added some extra lines to see what is happening an these were my conclusions. Here is the code:
#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int *sort(int *array)
{
int finish = 1;
while (finish = 1)
{
finish = 0;
for (int i = 0; i <= sizeof(array); i++)
{
if ((array + i) > (array + i + 1))
{
swap(array + i, array + i + 1);
finish = 1;
}
}
}
return array;
}
int main()
{
int s, res;
printf("Give me the size of the array being sorted(larger than 1) : ");
do
{
res = scanf("%d", &s);
if (res != 1)
{
printf("Wrong Input!\n");
exit(1);
}
if (s < 2)
printf("Only numbers equal or larger than 2\n");
} while (s < 2);
int array[s];
for (int i = 0; i < s; i += 1)
{
scanf("%d", array + i);
printf("%d %d %d\n\n", *(array + i), i, i < s); // I used this to check if my values were ok
}
printf("end of reading the array"); //I added this line to see if I would exit the for loop. I am not seeing this message
sort(array);
printf("\n");
for (int i = 0; i < sizeof(array); i++)
printf("%d\n\n", array + i);
printf("Array has been sorted! Have a nice day!\n\n************************************************************");
return 0;
}
See the annotations in the code:
#include <stddef.h> // size_t 1)
#include <stdio.h>
#include <stdlib.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int *sort(int *array, size_t size) // needs an extra parameter to know the size of the array
{
int finish = 1;
while (finish /* = 1 * you don't want assignment, you want comparison: */ == 1)
{
finish = 0;
for (int i = 0; i /* <= sizeof(array) */ < size - 1; i++) // i should be of type size_t
{
// if ((array + i) > (array + i + 1)) you are not dereferencing:
if(array[i] > array[i + 1])
{
// swap(array + i, array + i + 1); // easier to read imho:
swap(&array[i], &array[i + 1]);
finish = 1;
}
}
}
return array; // why does this function return anything? it is never used.
}
int main()
{
int s; /* , res; no need for an extra variable res */
printf("Give me the size of the array being sorted(larger than 1) : ");
do
{
// res = scanf("%d", &s);
// if (res != 1)
if (scanf("%d", &s) != 1)
{
printf("Wrong Input!\n");
// exit(1); // should be EXIT_FAILURE. Use return instead of exit() when in main().
return EXIT_FAILURE;
}
if (s < 2)
printf("Only numbers equal or larger than 2\n");
} while (s < 2);
int array[s];
for (int i = 0; i < s; /* i += 1* idiomatic: */ ++i) // size_t would be the correct type for s and i.
{
scanf("%d", /* array + i use indexes: */ &array[i]);
printf("%d %d %d\n\n", array[i], i, i < s); // again: indexes. i < s is allready ensured by the condition of the for-loop
}
printf("end of reading the array");
// sort(array); // sort will have no idea about the size of array use
sort(array, s); // instead.
printf("\n");
for (int i = 0; i < /* sizeof(array) 2) */ s; i++)
printf("%d\n\n", /* array + i * again you don't dereference */ array[i]);
printf("Array has been sorted! Have a nice day!\n\n************************************************************");
return 0;
}
1) size_t is the type that is guaranteed to be big enough to hold all sizes of objects in memory and indexes into them. The conversion specifier for scanf() is "%zu".
2) sizeof(array) in main() will yield the number of bytes in array, but you want the number of elements so you'd have to use sizeof(array) / sizeof(*array). But thats not needed since you already know its size. It is s.
This line
printf("end of reading the array");
has no line feed at the end of the string. This is a problem because printf is part of the family of functions called "buffered IO". The C library maintains a buffer of the things you want to print and only sends them to the terminal if the buffer gets full or it encounters \n in the stream of characters. You will not see, end of reading the array on your screen until after you have printed a line feed. You only do this after calling sort(). So all you know is your program is getting into an infinite loop at some point before the end of sort.
So there are actually three loops that could be infinite: the for loop you identified, the while loop in sort and the for loop inside the while loop. As the other answers point out, you have made the classic mistake of using assignment in the while conditional
while (finish = 1)
// ^ not enough equals signs
Unless your C compiler is really old, it is probably outputting a warning on that line. You should heed warnings.
Also, you should learn to use a debugger sooner rather than later. Believe me, it will save you a lot of time finding bugs.
In the sort function sizeof(array) returns the size of the pointer. (you can check it by yourself using printf("%d", sizeof(array).
The solution is to change your function to:
int sort(int* array, size_t size) { ... }
and call it with the correct array size:
sort(array, s);
I've just started C read the man page but could not find the proper answer. So the code is below
void *p = malloc(10*sizeof(int));
int *q = p;
int NUMOFINT = 10;
for (int i = 0; i < NUMOFINT; i++){
printf("%i ", q[i]);
}
void *realloc(void *p, 20*sizeof(int));
for (int i = 0; i < 21; i++){
printf("%i ", q[i]);
and it is giving this error:
malloc.c: In function ‘main’:
malloc.c:31:24: error: expected declaration specifiers or ‘...’ before numeric constant
I did not quite understand that the size format was ok for malloc() but not ok for realloc. So how do I correct the error?
Edit:
so when I make it as:
void *morep = realloc(p, 20*sizeof(int));
int *q2 = morep;
for (int i = 0; i < 20; i++){
printf("%i ", q2[i]);
}
it prints out q2[11] as 135121
This
void *realloc(void *p, 20*sizeof(int));
is wrong. You want
p = realloc(p, 20*sizeof(int));
Incidentally, this line is also a problem (but will compile fine):
for (int i = 0; i < 21; i++){
You allocated p to 20*sizeof(int) bytes, so element 20 is past the end of the array. You want:
for (int i = 0; i < 20; i++){
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int *temp; /* To use with realloc, it's more secure */
void *p = malloc(10*sizeof(int));
int *q = p;
int NUMOFINT = 10;
/* dont forget to compile with -std=99 flag, if you use this kind of for loop */
for (int i = 0; i < NUMOFINT; i++){
printf("%i ", q[i]);
}
printf("\n");
/* It's more secure to use this kind of realloc */
temp = realloc (p, 20 * sizeof(int) );
if (temp == NULL)
{
fprintf(stderr,"Reallocation failed --> %s\n", strerror(errno));
free(p);
exit(EXIT_FAILURE);
}
else
{
p = temp;
}
/* Zeroing after realloc */
for (int i = NUMOFINT; i < 21; i++)
q[i] = 0;
for (int i = 0; i < 21; i++)
{
printf("%i ", q[i]);
}
printf("\n");
return 0;
}
realloc can tries to expand the existing memory block in heap, if its not possible it will allocate a new separate block of memory for the new size and it will copy the data from old memory block to the new memory block also.
So if realloc returns the address same as p then it just expands the old memory block. Or else we have to free the old memory block and start using the new memory block returned by realloc.
#define NUMOFINT 10
#define NUMOFINT_NEW 20
void *p = malloc(NUMOFINT * sizeof(int));
int *q = p;
void *temp = NULL;
for (int i = 0; i < NUMOFINT; i++)
{
printf("%i ", q[i]);
}
temp = realloc(p, NUMOFINT_NEW * sizeof(int));
if (temp == NULL)
{
exit(0);
}
else if (temp != p)
{
free(p);
p = temp;
}
//else temp is equal to p
for (int i = 0; i < NUMOFINT_NEW; i++)
{
printf("%i ", q[i]);
}
Here q[0] to q[9] will have the values(0, 1, 2..9) assigned, and the rest (q[10] to q[19]) will have garbage value. We have not memset the newly allocated memory to 0 also.
you can memset also before for loop,
memset((q + NUMOFINT), 0, (NUMOFINT_NEW - NUMOFINT));
Mistakes in your program are
1) compilation error because
void *realloc(void *p, 20*sizeof(int)); This statement doesn;t looks like a function call.
2) for (int i = 0; i < 21; i++) - After memory is realloced to 20 elements, you can access only upto 19th, accessing 20th may leads to crash(undefined behaviour).
3) it prints out q2[11] as 135121 - Newly reallocated memory is neither memset to 0 nor assigned any meaningful values.