Why am I getting errors when debugging realloc? - arrays

int *dynArr(int* arr, int n, int isEven) {
int count = 0;
int* t = (int*)calloc(n, sizeof(int));
assert(t);
if (isEven == 1) {
for (int i = 0; i < n; i++) {
if (arr[i] % 2 == 0) {
t[count++] = arr[i];
}
}
}
t = (int*)realloc(*t, count * sizeof(int));
return t;
}
void main() {
int a[] = { 1,8,3,6,11 };
int n = sizeof(a) / sizeof(int);
int isEven = 1;
int* arr = dynArr(a, n, isEven);
for (int i = 0; i < n; i++) {
printf("%d", arr[i]);
}
}
The problem is when I'm returning the array I don't get any output, When I'm debugging I get this error: "Unhandled exception at 0x7A08B54D (ucrtbased.dll) in homelab8.exe: 0xC0000005: Access violation reading location 0x00000004."
Someone have an idea how do I fix this?

First of all, you are passing a bad parameter to realloc. This would easily have been caught had you been using your compiler's warnings.
The other major issue is that you are accessing n elements of the array pointed by arr, but it doesn't have n elements.
Since you have two values to return, you will need to return through arguments (or return a struct).
// Returns 0 on success.
// Returns -1 and sets errno on error.
int filter_even_or_odd(
int **filtered_arr_ptr, // The address of a variable that accepts output.
size_t *filtered_n_ptr, // The address of a variable that accepts output.
int *arr,
size_t n,
int keep_even // Keep even or keep odd?
) {
size_t filtered_n = 0;
int *filtered_arr = malloc( sizeof(int) * n );
if (!filtered_arr)
return -1;
int to_keep = keep_even ? 0 : 1;
for ( size_t i = 0; i < n; i++ ) {
if ( arr[i] % 2 == to_keep ) {
filtered_arr[ filtered_n++ ] = arr[i];
}
}
int *tmp = realloc( filtered_arr, sizeof(int) * filtered_n );
if (tmp)
filtered_arr = tmp;
*filtered_arr_ptr = filtered_arr;
*filtered_n_ptr = filtered_n;
return 0;
}

Related

How to solve this problem (throw an exception)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
void input_count(int*);
int* input_values(int);
void show_result(int**, int);
int main()
{
int count = 0;
input_count(&count);
int* array = input_values(count);
show_result(&array, count);
return 0;
}
void input_count(int* count)
{
do
{
printf("배열의 개수는? (0보다 커야합니다) ");
scanf("%d", count);
} while (*count <= 0);
}
int* input_values(int count)
{
int* array = (int*)malloc(sizeof(int) * count);
for (int i = 0; i < count; ++i)
{
printf("%d번째 값은? ", i);
scanf("%d", array + i);
}
return array;
}
void show_result(int** array, int count)
{
int max = 0, min = INT_MAX;
int* max_address = NULL, *min_address = NULL;
for (int i = 0; i < count; ++i)
{
if (*array[i] > max)
{
max_address = *array + i;
max = *max_address;
}
if (*array[i] < min)
{
min_address = *array + i;
min = *min_address;
}
}
printf("최대 원소의 주소: %p, 값: %d\n", max_address, max);
printf("최소 원소의 주소: %p, 값: %d\n", min_address, min);
}
I've only been studying programming for 10 days, so my skills are lacking. But I want to solve this problem.
The show_result function throws an exception:
Exception thrown(0x00007FF6BE02596B, Main.exe): 0xC0000005: 0xFFFFFFFFFFFFFFFF 위치를 읽는 동안 액세스 위반이 발생했습니다.
Images:
I think Null is the problem, but I don't know the mean that is back reference.
There is no sense to pass the pointer to the dynamically allocated array by reference through a pointer to it
show_result(&array, count);
because the pointer is not changed within the function show_result.
So declare the function like
void show_result( const int *, size_t );
and call it like
show_result( array, count);
The if statements
if (*array[i] > max)
and
if (*array[i] < min)
use invalid expressions. You have to write at least like
if ( ( *array )[i] > max)
and
if ( ( *array )[i] < min)
You will not have such a problem if will declare the function as shown above.
Also setting the variable max to 0
int max = 0, min = INT_MAX;
does not make sense. As the element type of the array is int then it can contain all elements set by negative numbers. In this case you will get a wrong result.
The function can be defined for example the following way
void show_result( const int *array, size_t count)
{
const int *max_address = array;
const int *min_address = array;
for ( size_t i = 1; i < count; ++i )
{
if ( *max_address < array[i] )
{
max_address = array + i;
}
else if ( array[i] < *min_address )
{
min_address = array + i;
}
}
if ( count != 0 )
{
printf( "최대 원소의 주소: %p, 값: %d\n", ( const void * )max_address, *max_address );
printf( "최소 원소의 주소: %p, 값: %d\n", ( const void * )min_address, *min_address );
}
else
{
// output a message that an empty array is passed
}
}

Two sum leetcode clang

I practice in c language, here is the exercise:
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example :
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].
Here my attempt:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
static int r[2];
for(int i=0;i<numsSize;i++){
for(int j=0;j<numsSize;j++){
if(i!=j&&(nums[i]+nums[j])==target){
r[0]=i;
r[1]=j;
}
}
}
return r;
}
But Irecieve a wrong answer:
enter image description here
The function definition does not satisfies the requirement specified in the comment
Note: The returned array must be malloced, assume caller calls free()
Moreover the parameter
int* returnSize
is not used within your function definition.
It seems the function should be defined the following way as it is shown in the demonstration program below. I assume that any element in the source array can be present in the result array only one time.
#include <stdio.h>
#include <stdlib.h>
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int *twoSum( int *nums, int numsSize, int target, int *returnSize )
{
int *result = NULL;
*returnSize = 0;
for (int i = 0; i < numsSize; i++)
{
for (int j = i + 1; j < numsSize; j++)
{
if (nums[i] + nums[j] == target)
{
int unique = result == NULL;
if (!unique)
{
unique = 1;
for (int k = 1; unique && k < *returnSize; k += 2)
{
unique = nums[k] != nums[j];
}
}
if (unique)
{
int *tmp = realloc( result, ( *returnSize + 2 ) * sizeof( int ) );
if (tmp != NULL)
{
result = tmp;
result[*returnSize] = i;
result[*returnSize + 1] = j;
*returnSize += 2;
}
}
}
}
}
return result;
}
int main( void )
{
int a[] = { 2, 7, 11, 15 };
int target = 9;
int resultSize;
int *result = twoSum( a, sizeof( a ) / sizeof( *a ), target, &resultSize );
if (result)
{
for (int i = 0; i < resultSize; i += 2 )
{
printf( "%d, %d ", result[i], result[i + 1] );
}
putchar( '\n' );
}
free( result );
}
The program output is
0, 1
Though as for me then I would declare the function like
int *twoSum( const int *nums, size_t numsSize, int target, size_t *returnSize );
The brute force approach is very simple to this problem.
int* twoSum(int* arr, int n, int t, int* returnSize){
int *res=malloc(2*sizeof(int));
*returnSize=2;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if((arr[i]+arr[j])==t)
{
res[0]=i;
res[1]=j;
goto exit;
}
}
}
exit:
return res;
}

Why this counting sort return input instead of sorted table?

I'm writing counting sort in C. N is the number of elements in table which is to be sorted, k is max value that any of this element can be. However, this code, leaves me with the same table as the input. What's wrong?
void countingSort(int *tab, int n, int k) {
int *counters = (int *)malloc(k * sizeof(int));
int *result = (int *)malloc(n * sizeof(int*));
for (int i = 0; i < k; i++) {
counters[i] = 0;
}
for (int i = 0; i < n; i++) {
counters[tab[i]]++;
}
int j = 0;
for (int i = 0; i < k; i++) {
int tmp = counters[i];
while (tmp--) {
result[j] = i;
j++;
}
}
tab = result;
}
There are some problems in your code:
int *result = (int *)malloc(n * sizeof(int*)); uses an incorrect size. The array element type is int, not int*. You should write:
int *result = (int *)malloc(n * sizeof(int));
or better:
int *result = (int *)malloc(n * sizeof(*result));
note also that the cast is useless in C, unlike C++ where it is mandatory:
int *result = malloc(n * sizeof(*result));
you could avoid the extra initializing loop by using calloc():
int *counters = calloc(n, sizeof(*counters));
a major problem: the result array is never returned to the caller: tab = result; just modifies the argument value, not the caller's variable. You should instead use the tab array to store the results directly.
you do not free the arrays, causing memory leaks.
you do not test for allocation success, causing undefined behavior if memory is not available. You should return an error status indicating this potential problem.
Here is a corrected version:
// assuming all entries in tab are > 0 and < k
int countingSort(int *tab, int n, int k) {
int *counters = calloc(k, sizeof(*counters));
if (counters == NULL)
return -1;
for (int i = 0; i < n; i++) {
counters[tab[i]]++;
}
int j = 0;
for (int i = 0; i < k; i++) {
int tmp = counters[i];
while (tmp--) {
tab[j++] = i;
}
}
free(counters);
return 0;
}
You pass tab to the function by pointer. However you need to change not the value, but address of the variable. So you should pass address of the pointer to countingSort.
void countingSort(int **tab, int n, int k)

struct pointer as return type

I want to print kk[i].data[j] but it is not printing at all.
intarr_save_binary is returning 2. I expect to get 0.
int k = sizeof(kk) / sizeof(kk[0]); gives 0. I'm expecting to get 5.
Did I properly allocate the memory?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int len;
int *data;
}intarr_t;
#define MAX 5
intarr_t* intarr_create(unsigned int len) {
intarr_t* new_intarr = (intarr_t*)malloc(sizeof(intarr_t));
if (!new_intarr) return NULL;
new_intarr->data = (int*)malloc(len * sizeof(int));
new_intarr->len = len;
return new_intarr;
}
int intarr_save_binary(intarr_t* ia, const char* filename) {
if (!ia) return 1;
if (!ia->data) return 2;
FILE* f = fopen(filename, "w");
if (!f) return 3;
if (fwrite(&ia->len, sizeof(ia->len), 1, f) == 1) {
fprintf(f, "%d ", ia->len);
}
else {
return 4;
}
if (fwrite(ia->data, sizeof(ia->data), ia->len, f) == ia->len) {
fclose(f);
return 0;
}
else {
fclose(f);
return 5;
}
}
int main() {
intarr_t *ia = (intarr_t*)malloc(MAX*sizeof(intarr_t));
int i;
int j;
for (j = 0; j < MAX; j++) {
ia[j].len = j + 1;
}
for (j = 0; j < MAX; j++) {
ia[j].data = (int*)malloc(ia[j].len * sizeof(int));
}
for (j = 0; j < MAX; j++) {
for (i = 0; i < ia[j].len; i++) {
ia[j].data = (i + 1) * j;
}
}
char name[20] = "myfile.txt";
int d;
printf("%d \n", intarr_save_binary(ia, name));
intarr_t *kk;
kk = intarr_create(MAX);
int k = sizeof(kk) / sizeof(kk[0]);
printf("%d\n",k);
for (j = 0; j < k; j++) {
for (i = 0; i < kk[j].len; i++) {
printf("%d: %d\n", i, kk[j].data[i]);
}
printf("\n");
}
free(kk);
return 0;
}
intarr_save_binary is returning 2. I expect to get 0.
for (j = 0; j < MAX; j++) {
for (i = 0; i < ia[j].len; i++) {
ia[j].data = (i + 1) * j;
}
}
This zeroes ia[0].data on the very first pass through the double loop. (ia[0].data = (0 + 1) * 0 gives 0).
Thus ia->data is 0, and !ia->data is true, making the function return 2.
int k = sizeof(kk) / sizeof(kk[0]); gives 0. I'm expecting to get 5.
You obviously expect sizeof kk to give the total amount of memory allocated for kk.
And that is what you get, actually -- the total amount of memory allocated for intarr_t *, which is the type of kk at that point. That most likely results in 4 or 8, depending on your architecture. What it is not is whatever len * sizeof(int) resulted in when you called intarr_create(). As #BoPersson commented, if you allocate the memory yourself, you have to remember yourself how much you allocated.
The sizeof kk / sizeof kk[0] "trick" only works if kk actually is an array, i.e. if it has been declared as such within the scope of you using the sizeof operator on it so the compiler can "see" its size.
So, as you have an int and an int * in your struct kk[0], which together are very likely to require more memory than an intarr_t *, the integer division results in 0.
You might also take note that free() is not recursive. With free(kk), you are leaking all the memory you allocated for all the data members. For every malloc(), there needs to be a corresponding free(). (And it does matter even if the program ends right after that one free(), as not all operating systems can / will protect you from this error.)

reallocation of 2d arrays in c

I want to reallocate a 2d array, so that the arrays in the second array become bigger, so the things I want to store are bigger than the arrays I want to store them in and I want to make the arrays bigger. The problem is that I do not really know how to do this. I got it to compile without errors, but in Valgrind I saw a lot of memory errors, so I do something wrong. I saw a previous question about this here but I do not really understand it, so any help and explanation on how to do this would be greatly appreciated.
I have this so far.
int **create2darray(int a, int b) {
int i;
int **array;
array = malloc(a * sizeof(int *));
assert(array != NULL);
for (i = 0; i < a; i++) {
array[i] = calloc(b, sizeof(int));
assert(array[i] != NULL);
}
return array;
}
int **reallocArray(int **array, int size, int i) {
int i;
int **safe_array;
safe_array = realloc(*array ,2 * size);
assert(safe_array != NULL);
array = safe_array;
return array;
}
void free2DArray(int **array, int m) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
}
int main(int argv, char *argc[]) {
int i;
int size;
int **testArray = create2darray(1, 10);
size = 10;
for(i = 0; i < size; i++) {
testArray[0][i] = 2;
}
testArray[0] = reallocArray(testArray, size, 0);
size = 2 * size;
for(i = 9; i < size; i++) {
testArray[0][i] = 3;
}
for(i = 0; i < size; i++) {
printf("%d", testArray[0][i]);
free2DArray(testArray, size);
}
return 0;
}
You need a function reallocArray which realaoctes the outer array and all the inner arrays too.
Adapt youre code like this:
#include <malloc.h>
int **reallocArray( int **array, int oldSizeA, int newSizeA, int newSizeB )
{
// realloc the array of pointers ( allocates new memory if array == NULL )
int **safe_array = realloc( array, newSizeA * sizeof( int* ) );
assert(safe_array != NULL);
if ( safe_array == NULL )
return array;
array = safe_array;
// realloc the inner arrays of int ( allocates new memory if i >= oldSizeA )
for ( int i = 0; i < newSizeA; i ++ )
{
int *temp = NULL; // allocate new memory if i >= oldSizeA
if ( i < oldSizeA )
temp = array[i]; // reallocate array[i] if i < oldSizeA
temp = realloc( temp, newSizeB * sizeof( int ) );
assert( temp != NULL );
if ( temp == NULL )
return array;
array[i] = temp;
}
return array;
}
Use function reallocArray in your function create2darray to create your array. If the input paramter of ralloc is NULL, then new dynamic memory is allocated.
int **create2darray( int sizeA, int sizeB )
{
return reallocArray( NULL, 0, sizeA, sizeB );
}
First you have to free the inner arrays of int in a loop, then you have to free the array of pointers:
void free2DArray( int **array, int sizeA )
{
for (int i = 0; i < sizeA; i ++)
free( array[i] );
free( array );
}
int main( int argv, char *argc[] ){
int sizeA = 1;
int sizeB = 10;
int **testArray = create2darray( sizeA, sizeB );
for ( int i = 0; i < sizeB; i++ ) {
testArray[0][i] = 2;
}
int oldSizeA = sizeA;
int oldSizeB = sizeB;
sizeB = 2*sizeB;
testArray = reallocArray( testArray, oldSizeA, sizeA, sizeB );
for( int i = oldSizeB; i < sizeB; i++ ) {
testArray[0][i] = 3;
}
for( int i = 0; i < sizeB; i++ ) {
printf("%d", testArray[0][i]);
}
free2DArray(testArray, sizeA );
return 0;
}
In Free2DArray(), you free() the individual arrays of integers, but not the "outer" dimension of the array which holds the integer pointers.
You could add another call to free() after the loop to take care of that.
In main():
for(i = 0; i <size; i++) {
printf("%d", testArray[0][i]);
free2DArray(testArray, size);
}
you will end up free()-ing the (inner) integer arrays multiple times.
The call to free2DArray() should be outside the loop.

Resources