I keep getting a seg fault not sure why [duplicate] - c

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 1 year ago.
This code is to make and print a matrix out but i am not sure why i am getting seg fault, it is because I am not freeing memory, if so how would i free it?
void printMatrix(struct Matrix *M){
struct Matrix *temp = M;
for(int i=0; i< temp->rows;i++){
for(int j=0; j< temp->cols;j++){
printf("%.f",getVal(temp,i,j));
}
printf("\n");
}
}
void makeMatrix(struct Matrix *M, int row, int col, int num){
M = malloc(sizeof(struct Matrix));
M->rows=row;
M->cols=col;
M->m =malloc(100*sizeof(double)*M->rows*M->cols);
for(int i=0; i<M->rows;i++){
for(int j=0; j<M->cols;j++){
setVal(M,i,j,num);
}
}
free(M);
}
int main(int argc, char const *argv[]) {
struct Matrix *test;
makeMatrix(test,10,10,10);
printMatrix(test);
return 0;
}

Your makeMatrix function is wrong. Parameter M is a local variable when makeMatrix executed. Thereofre any changes to M are not visible when the function ends. As result test is not initialized when passed to printMatrix causing failure then the pointer is dereferenced.
The solution is returning M from the function by value.
struct Matrix *makeMatrix(int row, int col, int num){
struct Matrix *M = malloc(sizeof(struct Matrix));
if (!M) return NULL;
M->rows=row;
M->cols=col;
M->m =malloc(100*sizeof(double)*M->rows*M->cols);
if (!M->m) {
free(M);
return NULL;
}
for(int i=0; i<M->rows;i++){
for(int j=0; j<M->cols;j++){
setVal(M,i,j,num);
}
}
return M;
}
Usage:
struct Matrix *test = makeMatrix(10,10,10);
Moreover, malloc(100*sizeof(double)*M->rows*M->cols); looks a bit wasteful because it consumes 100x more memory than needed. I'm pretty sure that malloc(sizeof(double)*M->rows*M->cols); would suffice.

First, always have to check if the malloc successfully allocates memory. So after the first call to malloc, you should write something like that:
if(!M)
{
printf("malloc failed to allocate memory for M");
return;
}
and so on. Also you should free each memory space you allocated with malloc. In your case you should also free(M->m)

Related

Using realloc() to increase size of array when even number is typed (from function)

hi im trying to make my array increase its size with realloc from function when even number is typed, but the compiler is displying Segmentation Fault whatever number I type.Any ideas how can i fix this?
#include <stdio.h>
#include <stdlib.h>
int MakeArray(int n,int *ptr)
{
ptr = (int*) malloc(n*sizeof(int));
if(ptr==NULL)
{
puts("Allocation failed");
}
return *ptr;
}
int ReAllocArray(int n,int *ptr)
{
ptr = (int*) realloc(ptr,n*sizeof(int));
if(ptr==NULL)
{
puts("Reallocation failed");
}
return *ptr;
}
int main() {
int n;
int *ptr=NULL;
puts("Enter size of n");
scanf("%d",&n);
MakeArray(n,ptr);
puts("Entering even number is increasing the size of the array by 1");
for(int i =0;i<n;++i)
{
scanf("%d",&ptr[i]);
if(ptr[i]%2==0)
{
++n;
ReAllocArray(n,ptr);
}
}
puts("Your array is:");
for(int i =0;i<n;i++)
{
printf("%d",ptr[i]);
}
return 0;
}
You need to pass pointer to pointer to int to modify it or/and return the reference to the allocated memory
int *MakeArray(size_t n, int **ptr)
{
if(ptr)
{
*ptr = malloc(n*sizeof(**ptr));
if(!*ptr)
{
puts("Allocation failed");
}
}
return *ptr;
}
Same when you realloc
int *ReAllocArray(size_t n, int **ptr)
{
int *tmp = NULL;
if(ptr)
{
tmp = realloc(*ptr,n * sizeof(**ptr));
if(!tmp)
{
puts("Reallocation failed");
}
else
{
*ptr = tmp;
}
}
return tmp;
}
When you call it you need to pass pointer to pointer:
MakeArray(n,&ptr);
ReAllocArray(n,&ptr);
It would be worth checking what those functions return to know if allocations succeeded.
Also:
Use the correct type for sizes (size_t nor int)
Do not cast the result of malloc/realloc. If it does not compiler you are using the wrong (C++) compiler to compile the C code.
Use objects not types in sizeofs
When realloc use a temporary variable. Otherwise, you may have a memory leak
BTW you do not need the MakeArray function at all as realloc will work fine when you pass NULL pointer (it will simple not copy any data to the allocated memory)

does using malloc( ) inside a function free the allocated memory after its execution?

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.

C malloc/free double pointer of char via a function

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.

Segmentation Fault in C using calloc

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int queensonboard(int n,int m)
{
int count=0,i,j,flag,x[100];
char **board;
/* board= (char**)calloc(sizeof(char*),n);
for(i=0;i<n;i++)
{
board[i]= (char*)calloc(sizeof(char),m);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&board[i][j]);
}
}*/
// x==(int*)calloc(sizeof(int),n);
flag=0;
for(i=0;i<n;i++)
{
x[i]=0;
}
while(i>0)
{
while(x[i]<m)
{
x[i]++;
// if(board[i][x[i]]!='#')
// {
for(j=0;j<i;j++)
{
if(x[j]==x[i])
{
flag=1;
}
else if(x[j]-x[i]==abs(j-i))
{
flag=1;
}
else
{
flag=0;
}
}
if(flag==0 && i==n-1)
{
count++;
}
else if(flag==0)
{
i++;
}
//}
}
x[i]=-1;
i--;
}
printf("%d\n",count);
}
int main() {
int i,n,m,j;
scanf("%d",&i);
for(j=1;j<=i;j++)
{
scanf("%d %d",&n,&m);
queensonboard(n,m);
}
return 0;
}
This is the code. The program gives segmentation fault on dynamically allocating any of the arrays x or board.(Commented here.)
That is when i try to allocate with calloc.
Couldnt really figure out why this is happening. Tried changing thins and that but still happening.
The definition of calloc is as follows:
void *calloc(size_t num, size_t size);
num Number of elements to allocate.
size Size of each element.
You have your arguments swapped. It should be like this:
board = calloc(n, sizeof(char *));
for(i = 0; i < n; i++)
{
board[i]= calloc(m, sizeof(char));
}
Also, this line is incorrect:
x == (int*)calloc(sizeof(int), n);
This, is comparing the address of x to the address that calloc returns. The logic is incorrect too. The way you have x defined, it is an array of 100 ints.
If you want an array of int pointers, you need to do this:
int *x[100];
If you want a pointer to array of 100 ints, you need to do this:
int (*x)[100];
If you're simply trying to allocate memory for x, you've already accomplished that with your declaration:
int x[100];
The obvious explanation for a segmentation fault is that you are de-referencing an invalid pointer. The obvious way for that to happen would be for any of the calls to calloc to return NULL. And calloc does that when it fails. You are not checking the return value of calloc for errors and I think it very likely that one of the calls returns NULL because you supplied invalid parameters.
So, debug the problem by checking the return value of the calls to calloc, and checking the input parameters that you pass. I know it's frustrating to have to do this, but you must check for errors in all user input, and you must check the return values of all calls to memory allocation functions.
This line
x==(int*)calloc(sizeof(int),n)
where you perform comparison rather than assignment is also clearly problematic. You meant:
int *x = calloc(n, sizeof(int));
And yes, you have the arguments to calloc swapped as others point out. You should certainly fix that but I do not believe that to be the cause of your problem.

attempt to free memory causes error

I have declared the following struct:
typedef struct _RECOGNITIONRESULT {
int begin_time_ms, end_time_ms;
char* word;
} RECOGNITIONRESULT;
There is a method that creates an array of RECOGNITIONRESULT and fills it (for test purposes only):
void test_realloc(RECOGNITIONRESULT** p, int count){
int i;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
for (i = 0; i < count; i++){
(*p)[i].begin_time_ms = 2*i;
(*p)[i].end_time_ms = 2*i+1;
(*p)[i].word=(char *) malloc ( (strlen("hello"+1) * sizeof(char ) ));
strcpy((*p)[i].word,"hello");
}
}
The method to free memory is:
void free_realloc(RECOGNITIONRESULT* p, int count){
int i = 0;
if(p != NULL){
if (count > 0){
for (i = 0; i < count; i++){
free(p[i].word); //THE PROBLEM IS HERE.
}
}
free(p);
}
}
The main method calls those methods like this:
int main(int argc, char** argv)
{
int count = 10;
RECOGNITIONRESULT *p = NULL;
test_realloc(&p,count);
free_realloc(p,count);
return 0;
}
Then if I try to free the memory allocated for "word", I get the following error:
HEAP CORRUPTION DETECTED: after normal block (#63) at 0x003D31D8.
CRT detected that the application wrote to memory after end of heap buffer.
Using the debugger I've discovered that the crash occurs when calling free(p[i].word);
What am I doing wrong? How can I free he memory for the strings?
The problem is in your allocation of memory for word. strlen("hello"+1) should be strlen("hello")+1.
Since you appear to allocate a whole array of structures in one strike
RECOGNITIONRESULT **p;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
you can free them in one call to free() as well :
void free_realloc(RECOGNITIONRESULT *p, int count){
free(p);
}
And the strlen("hello"+1) is also wrong, as detected by Chowlett.

Resources