I am trying to write a C function to store a multiplication table from the range 0-x. The function I have written has a bug in it where it only stores either the first 2 or 3 rows of the table and the function is also never returning a value and I am very confused, any help is appreciated.
void makeTable (int x) {
int** table = malloc(x * sizeof(int*));
int i;
int q;
int* ptr;
for(i = 0; i <= x; i++){
ptr = calloc(x, sizeof(int));
for(q = 0; q <= x; q++){
ptr[q] = (i * q);
}
table[i] = ptr;
}
return table;
}
Here you access memory that you have not allocated. That is undefined behavior.
Correct would be to consider x elements not x+1.
for(q = 0; q < x; q++){
ptr[q] = (i * q);
Same goes with the outer loop also.
for(i = 0; i < x; i++){
Also few other things - returning from a function which is declared void (Undefined behavior). Not checking the return value of malloc and calloc is problematic.
So correct way to write the function would be
int** makeTable (int x) {
int** table = malloc(x * sizeof *table);
if(!table)
{
fprintf(stderr,"Error in mem alloc");
exit(1);
}
for(size_t i = 0; i < x; i++){
int * ptr = calloc(x, sizeof *ptr);
if(!ptr)
{
fprintf(stderr,"Error in mem alloc");
exit(1);
}
for(size_t q = 0; q < x; q++){
ptr[q] = (i * q);
}
table[i] = ptr;
}
return table;
}
Also somewhere in this program you should add the logic to free all these dynamically allocated memory using free.
Related
The dynamicRandomMatrix function should return a pointer to an array of n pointers each of which points to an array of n random integers.
I got it to print mostly correct, except the first number in the array. This is the output:
n=3: -2084546528, 59, 45
Can anyone help me figure out why the first number in the array is so small? I think it must be something to do with local variables and access or something, but I am not sure.
int** dynamicRandomMatrix(int n){
int **ptr;
ptr = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
int *address = randomArray(n);
ptr[i] = address;
}
return ptr;
free (ptr);
}
int* randomArray(int n){
int *arr;
arr = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
int num = (rand() % (100 - 1 + 1)) + 1;
arr[i] = num;
}
return arr;
free(arr);
}
int main(){
int **ptr;
int i;
ptr = dynamicRandomMatrix(3);
printf("n=3: ");
for (i = 0; i < 3; i++) {
printf("%d, ", *ptr[i]);
}
return 0;
}
In your code,
ptr = malloc(sizeof(int) * n);
is not correct, each element in ptr array is expected to point to a int *, so it should be ptr = malloc(sizeof(int*) * n);. To avoid this, you can use the form:
ptr = malloc(sizeof(*ptr) * n);
That said, all your free(array); and free (ptr); are dead code, as upon encountering an unconditional return statement, code flow (execution) returns to the caller, and no further execution in that block (function) takes place. Your compiler should have warned about this issue. If not, use proper flags to enbale all warnings in your compiler settings.
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)
I am working on something that needs pthread usage. Basically, I want to find the max on a matrix, but instead of doing all the work single-processed, I use pthreads to break it.
I use one struct, as defined below to enter multiple values to the findMaxPerArea function. The problem occurs, when I call pthread_create(...); there at the last line. The printf before it passes just fine.
Please don't be too hard on me, because I know this MUST be a stupid mistake. Any thoughts?
struct inputData{
int ** array;
int start, stop, cols, threadID;
int* localmax;
};
void* findMaxPerArea(void* tmp){
struct inputData* inp = (struct inputData*) tmp;
inp->localmax[inp->threadID] = 0;
int i, j;
for(i = inp->start; i < inp->stop; i++){
for(j = 0; j < inp->cols; j++){
if(inp->array[i][j] > inp->localmax[inp->threadID]) inp->localmax[inp->threadID] = inp->array[i][j];
}
}
}
int main(){
int N, p;
printf("Give me the number of threads\n");
scanf("%d", &p);
printf("Give me the number of rows and columns (one value)\n");
scanf("%d", &N);
int* localmax = malloc(p * sizeof(int));
pthread_t* threadArr = (pthread_t*) malloc(p*sizeof(pthread_t));
int** a = malloc(N * sizeof(int*));
for (int i = 0; i < N; i++) {
a[i] = malloc(N * sizeof(int));
}
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
a[i][j] = 5;
}
}
a[0][1] = 8;
a[1][1] = 13;
struct inputData* inputArray = (struct inputData*) malloc(p * sizeof(struct inputData));
for(int i = 0; i < p; i++){
inputArray[i].array = a;
inputArray[i].start = i*(N/p);
inputArray[i].stop = (N/p)*(i+1) - 1;
inputArray[i].cols = N;
inputArray[i].threadID = i;
inputArray[i].localmax = localmax;
printf("It passes this\n");
pthread_create((pthread_t*)threadArr[i], NULL, findMaxPerArea, (void*)&inputArray[i]);
}}
pthread_create((pthread_t*)threadArr[i], NULL, findMaxPerArea, (void*)&inputArray[i]);
Casting threadArr[i] to pthread_t* makes no sense, since you cast a value to a pointer. You instead want to omit the cast completely (since you're already dealing with an array of pthread_ts) and take the address of the ith element:
&threadArr[i]
this is quite basic but I've been trying to solve it for a few hours now with no success. This code is supposed to read 3 ints from user input and then, points according to the ints (n = how many, d = dimension, k is unrelated to this part) and create an array of them. For some reason it crashes on the second loop, where it fails to create the second point, but im not sure why. I think it might has something to do with malloc but I'm totally lost, would appreciate any help.
I inserted the input :
5 3 2
1.2 3.4 0.1
2 times before it crashed.
Code is below:
int main(){
double* pdata;
int n,d,k;
scanf("%d %d %d",&n,&d,&k );
SPPoint* parr [n];
for(int i=0; i<n; i++)
{
double darr [d];
for(int j = 0; j < d-1; j++)
{
scanf(" %lf", &darr[j]);
}
scanf(" %lf", &darr[d-1]);
pdata = darr;
parr[i] = spPointCreate(pdata, d, i);
}
}
This is the code for the spPointCreate function:
struct sp_point_t{
double* data;
int dim;
int index;
};
SPPoint* spPointCreate(double* data, int dim, int index){
SPPoint* point = malloc(sizeof(SPPoint*));
if(point == NULL)
{
return NULL;
}
point->data = (double*) malloc(sizeof(data));
for( int i=0 ; i<dim ; i++)
{
point->data[i] = data[i];
}
point->dim = dim;
point->index = index;
return point;
}
SPPoint* point = malloc(sizeof(SPPoint*));
should be: struct SPPoint* point = malloc(sizeof(*point));
point->data = (double*) malloc(sizeof(data));
should be point->data = malloc(dim * sizeof(*point->data));
since you want to allocate dim doubles for your point.
Code is mis-allocating in 2 places
// Bad
SPPoint* spPointCreate(double* data, int dim, int index){
SPPoint* point = malloc(sizeof(SPPoint*)); // allocate the size of a pointer
...
point->data = (double*) malloc(sizeof(data)); // allocate the size of a pointer
Instead avoid mis-coding the type and allocate to the the size of the de-referenced variable.
Also need to allocate N objects.
SPPoint* spPointCreate(double* data, int dim, int index){
size_t N = 1;
SPPoint* point = malloc(sizeof *point * N);// allocate the size of `*point` * N
...
assert(dim >= 0);
N = dim;
point->data = malloc(sizeof *(point->data) * N);
BTW, casting the result of malloc() not needed.
2nd allocation would benefit with a NULL check. More complicated as dim may be 0 and a malloc() return of NULL in that case is OK.
N = dim;
point->data = malloc(sizeof *(point->data) * N);
if (point->data == NULL && N > 0) {
free(point);
return NULL;
}
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.