I need to find all the prime factors of a number. I have written this code, but when I try to reallocate the pointer array in calculatePrimes function using realloc, gcc gives error that i have not allocated the pointer before using realloc. I know I can pass the double pointer and use malloc inside the calculatePrimes function or, use a single pointer and return the value.
Code:
#include "stdio.h"
#include <math.h>
#include <stdlib.h>
void calculatePrimes(int max, int** array){
int size=1, i;
*array[0]=2;
for(i=0; i<max; i++){
if(isPrime(i)){
*array = (int *)realloc(**array, (++size)*sizeof(int));
*array[size-1]=i;
}
}
}
int isPrime(int value){
int i=2, root = sqrt(value);
for(;i<root;i++){
if(value%i==0) return 0;
}
return 1;
}
void main(int argc, char*argv[]){
int input = atoi(argv[1]), numPrimes;
int *primes=(int *)malloc(sizeof(int));
calculatePrimes(input, &primes);
numPrimes=sizeof(primes)/sizeof(int);
printf("%d\n", numPrimes);
free(primes);
}
Incorrect usage of realloc(). The correct is below:
*array = realloc(*array, (++size)*sizeof(int));
When you pass **array to realloc() you pass the value of the first element of the array that is int instead of int*.
Note that I've also removed the cast. In C, it's not needed and can hide certain problems you don't want hidden. Specifically, it can give you the wrong function signature for malloc/realloc which, if your int and void* type aren't compatible, can lead to corrupted pointers.
Related
when trying to print the values of struct variables after the function returns it prints some random text (which I think is due to memory allocation error)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char s1[20];
char s2[20];
int n1;
} TEST;
void allocate(TEST *T, int n){
T = malloc(sizeof(TEST)*n);
for(int i=0; i<n; i++){
sprintf((T+i)->s1, "string 1 of %d", i);
sprintf((T+i)->s2, "string 2 of %d", i);
(T+i)->n1 = i;
}
}
int main(){
TEST *T;
int n = 3;
allocate(T, n);
for(int i=0; i<n; i++){
printf("%s\n%s\n%d\n\n", (T+i)->s1, (T+i)->s2, (T+i)->n1);
}
}
No, C absolutely does not call free automatically for you.
The issue in your program is that T in the caller to allocate is not changed. C is strictly a pass by value language.
One solution is to change the type of T to TEST** in allocate:
void allocate(TEST **T, int n){
with
allocate(&T, n);
in main. You then call free in main.
The program causes undefined behaviour by passing uninitialized T to the function. Furthermore you never return the new pointer value from the function back to main.
The pointer to new memory is an output of the function, not an input. So it should be a return value, not a parameter. For example:
TEST* allocate(int n)
{
TEST* T = malloc(sizeof(TEST)*n);
// etc.
return T;
}
and then in main:
TEST* T = allocate(n);
// ... use T ...
free(T);
As said by the already given answers you need to call free to free the memory.
You want to allocate the pointed memory area, so you need a TEST**:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char s1[20];
char s2[20];
int n1;
} TEST;
void allocate(TEST **T, int n){
*T = malloc(sizeof(TEST)*n);
for(int i=0; i<n; i++){
sprintf((*T+i)->s1, "string 1 of %d", i);
sprintf((*T+i)->s2, "string 2 of %d", i);
(*T+i)->n1 = i;
}
}
int main(){
TEST *T;
int n = 3;
allocate(&T, n);
for(int i=0; i<n; i++){
printf("%s\n%s\n%d\n\n", (T+i)->s1, (T+i)->s2, (T+i)->n1);
}
free(T);
}
No. The problem with your program is that T is passed by copy to allocate, and the address to the allocated memory is assigned to this copy. To fix, you could make the first allocate parameter **T, pass in the address of T in main, and dereference the pointer to pointer in allocate and assign to it.
No, it doesn't. You need to free() malloc()ated memory yourself.
Your program, as is, leaks memory... but for this particular program it doesn't matter an awful lot since that memory is freed when the process dies.
I already read these links: link1 and link2.
However, if I execute the following piece of code inside valgrind:
valgrind --tool=memcheck --leak-check=full --num-callers=40 --show-possibly-lost=no
I can see that the memory is not correctly freed.
#include <stdio.h>
#include <stdlib.h>
void printVector(char ** vector, int N);
void allocateVector(char *** vector, int N, int M);
void deallocateVector(char *** vector, int N);
int main(int argc, char * argv[]) {
char ** vector;
int N=6;
int M=200;
allocateVector(&vector,N,M);
printVector(vector,N);
deallocateVector(&vector,N);
}
void allocateVector(char *** vector, int N, int M) {
*vector=(char **) malloc(N*sizeof(char *));
int i;
for(i=0; i<N; i++) {
(*vector)[i]=(char *) malloc(M*sizeof(char));
(*vector)[i]="Empty";
}
}
void deallocateVector(char *** vector, int N) {
int i;
char ** temp=*vector;
for(i=0; i<N; i++) {
if(temp[i]!=NULL) {
free(temp[i]);
}
}
if(temp!=NULL) {
free(temp);
}
*vector=NULL;
}
I cannot find where is the mistake.
The problem is here:
for(i=0; i<N; i++) {
(*vector)[i]=(char *) malloc(M*sizeof(char));
(*vector)[i]="Empty";
}
You allocate space and store a pointer to it in (*vector)[i]. Then you overwrite that pointer with the address of the string constant "Empty".
This causes two issues:
The memory returned by malloc is leaked, as you no longer have a reference to it.
When you later call free, you're passing it the address of a string constant instead of the address of an allocated block of memory. Calling free in this way invokes undefined behavior.
You need to use the strcpy function to copy the string constant into the memory you allocated:
for(i=0; i<N; i++) {
(*vector)[i]=malloc(M);
strcpy((*vector)[i],"Empty");
}
Also, don't cast the return value of malloc, and sizeof(char) is defined to be 1 and can be omitted.
I don't know what I'm doing wrong I'm stuck on this for the past two hours. Any help would be highly appreciated.
My code is the following:-
#include <stdio.h>
int* findLargest(int* arr,int size){
return &arr[size-1];
}
int main(){
int size=3;
int arr[3]={3,4,5};
int* largest=&arr[size-1];
int* largest2=malloc(100);
largest2=findLargest(*arr,size);
printf("%d",largest);
printf("%d",*largest2);
}
I get a garbage value when I execute.
Only pass arr to findLargest, this is already a pointer
largest2=findLargest(arr,size);
printf contents of largest, not the pointer itself
printf("%d\n", *largest);
Also, I'm not sure why you have the line:
int* largest2=malloc(100);
The malloc'd pointer is immediately lost in the next line when you assign to largest2 again.
I would also consider assigning size like so:
int size = sizeof(arr)/sizeof(arr[0]);
This is safer if you change the contents of arr in the future.
With all these changes main looks like:
int main()
{
int arr[3]={3,4,5};
size_t size = sizeof(arr)/sizeof(arr[0]);
int* largest=&arr[size-1];
int* largest2=findLargest(arr,size); // Only pass array to findLargest, this is already a pointer
printf("%d\n", *largest); // printf contents of largest, not the pointer
printf("%d\n", *largest2);
}
The problem here is this line
printf("%d",largest);
Where you're not de-referencing the pointer. Nor is there a space or new line after the value causing more confusion.
you can't edit address of pointer, you've to edit value of pointer
like this:
int * v = malloc(sizeof(int)); //WRONG
int n=54;
v=&n;
int * v = malloc(sizeof(int)); //CORRECT
int n=54;
*v=n;
Well, the problem was simple. Just in case someone runs into this confusion this can help.
The correct code is:
#include <stdio.h>
int* findLargest(int* arr,int size){
return &arr[size-1];
}
int main(){
int size=3;
int arr[3]={3,4,5};
int* largest=&arr[size-1];
int* largest2=malloc(100);
largest2=findLargest(arr,size);//Not findLargest(*arr,size)
printf("%d",*largest2);
}
Am sorting an array of strings (case insensitive).
qsort causes segmentation fault, probably my casting isn't proper.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *string1, const void *string2) {
char *a = (char*)(string1);
char *b = (char*)(string2);
printf("comparing %s AND %s\n", a, b);
return strcasecmp(a,b);
}
void sortListName(char **fileList, int noOfFiles) {
printf("Sorting\n");
qsort(fileList, noOfFiles, 260*sizeof(char), compare);
return;
}
**fileList = array of strings (filenames)
P.S. main() is obvious and works fine.
If this is all the code you have related to the qsort, it looks like you declared the comparePtr function pointer, but it's still not initialized; it's not pointing to your compare function (which is what I assume you wanted it to point to).
After that, a few more things:
1) comparePtr has the correct types, but compare does not. It needs to take in two const void*, but you have two const void**.
2) Once you fix the types, you could just pass compare to qsort, instead of making a function pointer and passing that.
3) I'm not convinced the first argument to qsort is correct. You want to be passing in the pointer to the first element in the array, which ought to just be fileList (I'm assuming it points to the first string in your array).
4) The third argument isn't correct either. fileList is a char**, meaning you're passing in an array of char *s, and hence the third argument should just be sizeof(char*), not the strlens of the strings.
I would adjust things so that you're just sorting a simple array, in this case of pointers to char - qsort will arrange for you to get pointers to two elements in that array (that is, char ** pointers), and some basic dereferencing is needed to get you to the "pointers to char" comparable via strcasecmp. #Mark likely has sussed out the source of the 260 in your unseen calling code, but I'm not a big fan of those kinds of 2d arrays in C.
The following functions for me, with an example main() to exercise it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *v1, const void *v2){
char *a = *(char **)v1;
char *b = *(char **)v2;
printf("comparing %s to %s\n", a, b);
return strcasecmp(a,b);
}
void sortListName(char **fileList, int noOfFiles){
printf("Sorting\n");
qsort(fileList, noOfFiles, sizeof(*fileList), compare);
return;
}
int
main(void)
{
char *filenames[] = {
"/var/www/icons/comp.gray.png",
"/var/www/error/HTTP_SERVICE_UNAVAILABLE.html.var",
"/var/www/icons/right.gif",
"/var/www/error/HTTP_NOT_IMPLEMENTED.html.var",
"/var/www/icons/pie3.png",
"/var/www/icons/pie2.png",
"/var/www/htdocs/manual/mod/mod_proxy_balancer.html",
"/var/www/htdocs/manual/programs/rotatelogs.html",
"/var/www/htdocs/manual/vhosts/mass.html",
"/var/www/icons/movie.png",
"/var/www/htdocs/manual/images/caching_fig1.png",
"/var/www/htdocs/htdig/search.html",
"/var/www/icons/generic.gif",
"/var/www/htdocs/manual/mod/quickreference.html",
"/var/www/icons/small/blank.png",
"/var/www/icons/image2.gif"
};
int i, nf = (int) (sizeof(filenames) / sizeof(filenames[0]));
puts("Unsorted:");
for (i = 0; i < nf; i++) {
puts(filenames[i]);
}
sortListName(filenames, nf);
puts("Sorted:");
for (i = 0; i < nf; i++) {
puts(filenames[i]);
}
return 0;
}
I am currently trying to learn C and I have come to a problem that I've been unable to solve.
Consider:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ELEMENTS 5
void make(char **array, int *array_size) {
int i;
char *t = "Hello, World!";
array = malloc(ELEMENTS * sizeof(char *));
for (i = 0; i < ELEMENTS; ++i) {
array[i] = malloc(strlen(t) + 1 * sizeof(char));
array[i] = strdup(t);
}
}
int main(int argc, char **argv) {
char **array;
int size;
int i;
make(array, &size);
for (i = 0; i < size; ++i) {
printf("%s\n", array[i]);
}
return 0;
}
I have no idea why the above fails to read back the contents of the array after creating it. I have literally spent an hour trying to understand why it fails but have come up empty handed. No doubt it's something trivial.
Cheers,
You need to pass the address of "array" into the function. That is, you need char ***. This is because you need to change the value of array, by allocating memory to it.
EDIT: Just to make it more complete, in the function declaration you need to have something like
void make(char ***array, int *array_size)
Then you need to call it using
make(&array, &size);
Inside the function make, allocate memory with
*array = malloc(ELEMENTS * sizeof(char *));
And change other places accordingly.
Also, as kauppi has pointed out, strdup will allocate memory for you, so you don't need to do malloc on each string.
Here is the working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ELEMENTS 5
void make(char ***array) {
char *t = "Hello, World!";
*array = malloc(ELEMENTS * sizeof(char *));
int i;
for (i = 0; i < ELEMENTS; ++i) {
(*array)[i] = strdup(t);
}
}
int main(int argc, char **argv) {
char **array;
make(&array);
int i;
for (i = 0; i < ELEMENTS; ++i) {
printf("%s\n", array[i]);
free(array[i]);
}
free(array);
return 0;
}
As the other have posted - there was unused size, and strdup allocates memory by itself, and it is nice to free the memory afterwards...
See PolyThinker's comment which is absolutely spot on.
In addition to the way you pass the array, you should check a few other issues:
Perhaps you should assign something to array_size in make(...)?
strdup(char*) allocates memory, the malloc for array[i] is not necessary.
You should free all the memory you allocate after you don't need it anymore.
You are passing the current value of array to make as a copy (on the stack). when you change array in make(), you're only changing the copy, not the actual variable. Try passing by reference with &, or make it a char *** and work with *array = ...
size is declared but gets no value assigned (that should happen in function make, I suppose).