Malloc 2d array is always NULL - c

I have been trying to dynamically allocate memory for structures. I keep on getting seg faults and I am not sure why. I reduced the code to a practice program to try and figure out whats wrong. This code compiles correctly with no errors:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int id;
}person;
person **new;
int main()
{
int x, size;
printf("How big is this? ");
scanf("%d", &size);
getchar();
if((person **)malloc(size*sizeof(person))==NULL);
{
printf("There was a problem\n");
exit(1);
}
person **new=(person **)malloc(size*sizeof(person **));
for(x=0; x<size ;x++)
{
new[x]=(person *)malloc(sizeof(person *));
new[x]->id=x*5;
}
for(x=0; x<size; x++)
{
printf("%d\t", new[x]->id);
free(new[x]);
}
free(new);
return 0;
}
But whenever I try to run the program it always triggers the if statement that checks for a NULL and exits. Whenever I take out the if statement it runs perfectly and gives me the right answer. So I am not really sure what is going wrong.

Following line has two issues:
if((person **)malloc(size*sizeof(person))==NULL);
Issue1: Memory leak
Issue2: Has ; at the end of if condition.
To fix these issues use:
person **new=(person **)malloc(size*sizeof(person *));
if(NULL == new)
{
printf("There was a problem\n");
exit(1);
}
Also as mentioned by francis you need to change your new[x] malloc statement:
new[x]=(person *)malloc(sizeof(person *));
To:
new[x]=(person *)malloc(sizeof(person));

Related

Segmentation fault (core dumped) error when running my program

so i am supposed to create a program that analyzes said text file and when i first ran it, i didn't have the text file created, but once i created it and tried to run the program i got a seg fault error and now i don't know how to fix it.
#include <stdio.h>
#include <string.h>
#define FILENAME "poems.txt"
int getWords(int maxWord, char words[][maxWord], FILE*);
int countLetters(char str_letter[]);
int countLowerCase(char str_lower[]);
int countVowels(char str_vowel[]);
int main()
{
int maxWord=50;
int numWord=0;
char words[numWord][maxWord];
char str_letter[75];
char str_lower[75];
char str_vowel[75];
FILE* fp;
int numLetter;
int numLower;
int numVowel;
fp=fopen(FILENAME, "r");
if(fp==NULL) {
printf ("poems.txt could not be found!\n");
}
else {
getWords(maxWord, words, fp);
countLetters(str_letter);
countLowerCase(str_lower);
countVowels(str_vowel);
printf ("There are %d letters in your file.\n", numLetter);
printf ("There are %d lower case letters in your file.\n", numLower);
printf ("There are %d vowels in your file.\n", numVowel);
fclose(fp);
}
return 0;
}
int getWords(int maxWord, char words[][maxWord], FILE* inFILE)
{
int numWord=0;
char poem;
while(fscanf(inFILE, "%s", &poem)==1){
words[numWord][maxWord]=poem;
numWord++;
}
numWord++;
return numWord;
}
int countLetters(char str_letter[])
{
int numLetter=0;
for(int i=0; i<strlen(str_letter); i++) {
if((str_letter[i]>'a' && str_letter[i]<'z')||(str_letter[i]>'A' && str_letter[i]<'Z'));
numLetter++;
}
return numLetter;
}
int countLowerCase(char str_lower[])
{
int numLower=0;
for(int i=0; i<strlen(str_lower); i++) {
if(str_lower[i]>'a' && str_lower[i]<'z');
numLower++;
}
return numLower;
}
int countVowels(char str_vowel[])
{
int numVowel=0;
for(int i=0; i<strlen(str_vowel); i++) {
if(str_vowel[i]=='a'||str_vowel[i]=='e'||str_vowel[i]=='i'||str_vowel[i]=='o'||str_vowel[i]=='u')
{
numVowel++;
}
else if(str_vowel[i]=='A'||str_vowel[i]=='E'||str_vowel[i]=='I'||str_vowel[i]=='O'||str_vowel[i]=='U')
{
numVowel++;
}
}
return numVowel;
}
You are making so many mistakes on your code, so i need to ask, you understands how dynamic memory allocation and pointers works in C? Is not like other languajes, you need to allocate memory before you access to them.
If you dont have a text file, your code works and the output is:
poems.txt could not be found!
So up to here everithings seems to work fine, but it doesn't.
Lets go to the line where you declare:
int maxWord=50;
int numWord=0;
char words[numWord][maxWord];
Here you are saying "SAVE ME AN ARRAY OF 0 POSITIONS AS COLUMNS AND 50 POSITIONS OF ROWS" so when you execute the following code in the function getWords, your code breaks.
while(fscanf(inFILE, "%s", &poem)==1){
words[numWord][maxWord]=poem;
numWord++;
}
Because the position:
words[1][maxWord]
isn't allocated.
You got two ways of allocate memory in C as far as i know, dynamic and static memory allocation.
I believe you came from learning another languaje like python or javascript where this types of things "works" but not in C.
If you want to solve this problems take a look to dynamic memory allocation and how C pointers works, you can make your code unstopable!

Segmentation fault in 2D array Dynamic Allocation

#include<stdio.h>
#include<stdlib.h>
struct Graph{
int V;
int E;
int **Adj;
};
struct Graph* adjMatrix(){
int u,v,i;
struct Graph *G;
G=(struct Graph*)malloc(sizeof(struct Graph));
if(!G){
printf("Memory Error!\n");
return;
}
printf("Enter number of nodes and number of edges:\n");
scanf("%d %d",&G->V,&G->E);
G->Adj=malloc((G->V)*(G->V)*sizeof(int));
for(u=0;u<(G->V);u++)
for(v=0;v<(G->V);v++)
G->Adj[u][v]=0; //This gives a segmentation fault.
printf("Enter node numbers in pair that connect an edge:\n");
for(i=0;i<(G->E);i++){
scanf("%d %d",&u,&v);
G->Adj[u][v]=1;
G->Adj[v][u]=1;
}
return(G);
}
int main(){
struct Graph *G;
int i,j,count=0;
G=adjMatrix();
for(i=0;i<G->V;i++){
for(j=0;j<G->V;j++){
printf("%d ",G->Adj[i][j]);
count++;
}
if(count==G->V)
printf("\n");
}
return 0;
}
The code shows segmentation fault when I tried to assign a value in 2D array i.e. at G->Adj[u][v]=0; but I don't know what is wrong with that? Because It's simply a assignment to the array.
#include<stdio.h>
#include<stdlib.h>
struct Graph{
int V;
int E;
int **Adj;
};
struct Graph* adjMatrix(){
int u,v,i;
struct Graph *G;
G=malloc(sizeof(struct Graph));
if(!G){
printf("Memory Error!\n");
return 0;
}
printf("Enter number of nodes and number of edges:\n");
scanf("%d %d",&G->V,&G->E);
//First problem was here this is how you allocate a 2D array dynamically
G->Adj=malloc((G->V)*sizeof(int*));
for(u=0;u<G->V;u++)
G->Adj[u]=malloc((G->V)*sizeof(int));
for(u=0;u<(G->V);u++)
for(v=0;v<(G->V);v++)
G->Adj[u][v]=0; //This gives a segmentation fault.
// i added some adjustment here to help you
printf("Enter node numbers in pair that connect an edge:\n");
for(i=0;i<(G->E);i++){
scanf("%d %d",&u,&v);
if(u>=G->V || v>=G->V){
printf("Error give the right input\n");
i--;}
else{
G->Adj[u][v]=1;
G->Adj[v][u]=1;}
}
return(G);
}
int main(){
struct Graph *G;
int i,j,count=0;
G=adjMatrix();
for(i=0;i<G->V;i++){
for(j=0;j<G->V;j++){
printf("%d ",G->Adj[i][j]);
count++;
}
if(count==G->V)
printf("\n");
}
return 0;
}
The segmentation fault is casued due-to error at the 2D array allocation method, as it us done at the following line:
G->Adj=malloc((G->V)*(G->V)*sizeof(int));.
which actually allocated a 1D buffer of (G->V)*(G->V) integers, so it can't enable a later access in syntax of 2D, like you want
In a nutshell: when allocation 2D array like you wish, you should first allocate the 1D array of pointers.
At your code, should be:
G->Adj = (int **)malloc(sizeof(int *)*G->V);
And then allocate G->V vectors per pointer:
for(i=0; i < G->V; i++)
{
G->Adj[i] = (int *)malloc(sizeof(int)*G->V);
}
furthermore, a good practice is to verify allocation result is not NULL (malloc failure), for each allocation
for general explanation on c vectors allocation you may read more at Method 2: the "can still use [r][c] syntax to access" way
Besides that, memory release is missing at the end of your program, so you should add calls to free() at the opposite order (vectors and then pointers)

Error while printing the given inputs

This code:
#include<stdio.h>
struct my_structure {
char name[20];
int number;
int rank;
};
int main()
{
int n,i;
scanf("%d",&n);
struct my_structure variable[n];
struct my_structure *ptr;
ptr = &variable;
for(i=0; i<n; i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
scanf("%d",&ptr->rank);
}
for(i=0; i<n; i++)
{
printf("NAME: %s\n", ptr->name);
printf("NUMBER: %d\n", ptr->number);
printf("RANK: %d", ptr->rank);
}
return 0;
}
It is not printing correctly. I want to print the 1st input first and then the second. But I'm getting the output like printing only the second input two times.
Two changes you need to do:-
ptr = variable ;
Then you can increase ptr in loop.(The use of scanf is not robust - how to do it better is shown in the end of the answer).
for(i=0;i<n;i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
...
ptr++;
}
After that again do the assignment ptr = variable;.
You can also do this (Illustration on the users code)
..
scanf("%s",ptr[i].name);
scanf("%d",&ptr[i].number);
...
printf("%s",ptr[i].name);
printf("%d",ptr[i].number);
Earlier you have type mismatch in assignment. You were assigning a struct my_structure (*)[n] to struct my_structure*. Check the return value of scanf and also check the value n (n>1).
You can do it on your way also:(Illustration on the users code)
struct my_structure (*ptr)[n] = &variable;
for(i=0;i<n;i++)
{
scanf("%s",(*ptr)[i].name);
scanf("%d",&((*ptr)[i].number));
scanf("%d",&((*ptr)[i].rank));
}
...
printf("%s",(*ptr)[i].name);
printf("%d",((*ptr)[i].number));
Correct way to use scanf would be:-(Notice that here 19 is used - otherwise there is a chance of buffer overrun - and this is being checked using this.This is one less than the size of the array because of the \0 character ) (Correct way)
if(scanf("%19s",ptr[i].name) != 1){
/* error in input */
fprintf(stderr,"Error in input\n");
exit(EXIT_FAILURE);
}
Compile your program with all warnings enabled. gcc -Wall -Werror progname.c.
Clearly you don't even need to use this pointer - why would you do that? You can simply use the array itself in the scanf or printf.

Stack Smashing Detected at End of Program

I am currently testing a program on a smaller scale to distinguish a problem when I attempt to exit the program by return 0; at the end of the main function.
Main.c
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
int main (void)
{
int i;
int Fin = 0;
Student sStu;
Array aAry;
Student *Stu = &sStu;
Array *Ary = &aAry;
InitArray(Ary, 1);
while(Fin != 2)
{
printf("Please choose a selection.\n");
printf("1. Add Student\n");
printf("2. Print Students\n");
printf("3. Exit\n");
scanf("%d", &i);
switch(i)
{
case 1:
{
AddStudent(Stu, Ary);
break;
}
case 2:
{
for(i = 0; i < Ary->Size; i++)
{
printf("%s %d\n", Stu[i].Name, Stu[i].IDn);
}
break;
}
case 3:
{
return 0;
}
}
}
}
Header.h
#ifndef HEADER_H_
#define HEADER_H_
typedef struct student
{
char Name[30];
int IDn;
}Student;
typedef struct array
{
Student *Student;
size_t Used;
size_t Size;
}Array;
void InitArray(Array *Ary, int InitSize);
void AddArray(Array *Ary);
Student AddStudent(Student *Stu, Array *Ary);
#endif
Grade.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Header.h"
void InitArray(Array *Ary, int InitSize)
{
Ary->Student = malloc(InitSize * sizeof(Student));
Ary->Used = 0;
Ary->Size = InitSize;
memset(&Ary->Student[0], 0 , sizeof(Student) * InitSize);
}
void AddArray(Array *Ary)
{
Student Stud;
if(Ary->Used == Ary->Size)
{
Ary->Size *= 2;
Ary->Student = realloc(Ary->Student, Ary->Size * sizeof(Student));
}
strcpy(Ary->Student[Ary->Used].Name, Stud.Name);
Ary->Student[Ary->Used].IDn = Stud.IDn;
Ary->Used++;
}
Student AddStudent(Student *Stu, Array *Ary)
{
int i;
printf("\nStudent ID numbers cannot be the same!\n");
printf("Please enter the student's name: ");
scanf("%s", Stu[Ary->Used].Name);
printf("Please enter the student's ID Number: ");
scanf("%d", &Stu[Ary->Used].IDn);
AddArray(Ary);
printf("\n");
return;
}
At the end of the file, when I try to return 0; I get this error:
* stack smashing detected *: ./a.out terminated
Segmentation fault (core dumped)
When I use valgrind, I get this output:
==9966== Invalid write of size 1
==9966== at 0x402C6C3: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9966== by 0x8048687: AddArray (in /home/ctj0033/CSCE_1040/Homework/2_Homework/2_Test/a.out)
==9966== by 0x804874B: AddStudent (in /home/ctj0033/CSCE_1040/Homework/2_Homework/2_Test/a.out)
==9966== by 0x804881C: main (in /home/ctj0033/CSCE_1040/Homework/2_Homework/2_Test/a.out)
==9966== Address 0x41f804c is 0 bytes after a block of size 36 alloc'd
valgrind terminates due to an fatal error during my attempt to exit my program.
It only happens at the end and I can print the contents of the struct array properly. I have looked into realloc(); since I am fairly sure the error lies within that, however I am uncertain precisely what I have done wrong. I have attempted to alter the way I allocate the memory in InitArray(); and the way I use realloc(); but to no avail.
What have I done wrong?
Your immediate problem is that you're trying to use an "invalid pointer". (Actually, it's a completely valid pointer, it just points to a wrong place)
sStu is a Student, and Stu is a pointer to it. But when you add your second student, you write to Stu[1] - which is the space after sStu. Most likely there's something else in this space, so when you write to Stu[1], you overwrite something else. (It's unpredictable exactly what will be in that space.)
It looks like you want to use Ary->Student everywhere you have Stu.
(If you do that, you might find some more problems - such as the fact that you check if you need to expand the array after writing to the next element)

Segmentation fault using strcpy

I have some troubles when using strcpy to copy an array of string inside a double pointer with allocated memory, but i can't understand why i get segmentation fault even if i have previously allocated memory.
Here is the code:
#include <stdio.h>
#include <string.h>
typedef struct Students {
int q_exams;
char **done_exams;
}Students;
int main() {
Students a;
int i;
char support[30];
printf("how many exams have you done ?\n");
scanf("%d",&(a.q_exams));
a.done_exams=malloc(sizeof(char*)*a.q_exams);
if(a.done_exams==NULL)
{
printf("out of memory\n");
return 0;
}
for(i=0;i<a.q_exams;i++)
{
printf("Insert the name of the exam\n");
scanf("%28s",support);
a.done_exams[i]=malloc(strlen(support)+1);
if(a.done_exams[i]==NULL)
{
printf("out of memory\n");
return 0;
}
strcpy(a.done_exams[i][0],support);
fflush(stdin);
}
return 0;
}
You need to pass an address of the initial character to strcpy, either like this
strcpy(&a.done_exams[i][0],support);
// ^
// Add an ampersand
or equivalently like this:
strcpy(a.done_exams[i] , support);
// ^
// Remove the second index
Currently, your code passes the value* of the initial character, rather than its address.
* The value is undefined at the time as well, but it is not the primary cause, because you should not be passing value at all.
This code is fixed
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Students {
int q_exams;
char **done_exams;
} Students;
int main()
{
Students a;
int i;
char support[49];
printf("how many exams have you done ?\n");
scanf("%d",&(a.q_exams));
a.done_exams = malloc(sizeof(char*) * a.q_exams);
if(a.done_exams==NULL)
{
printf("out of memory\n");
return 0;
}
for(i = 0 ; i < a.q_exams ; i++)
{
printf("Insert the name of the exam\n");
scanf("%48s",support);
a.done_exams[i] = malloc(strlen(support)+1);
if(a.done_exams[i] == NULL)
{
printf("out of memory\n");
return 0;
}
strcpy(a.done_exams[i]/*[0]*/, support);
/* ^ ^- this is wrong
* + pass the address to the array not the first element value
*
* if you had warnings turned on you would have seen this
*/
fflush(stdin);
}
return 0;
}
notice that
scanf("%48s", support);
requires
char support[49];
which is also fixed in the code.
See the man page of strcpy().
The first argument should be of type char *.
As per your code, the argument [a.done_exams[i][0]] is of type char. You need to pass a char * [starting address of the destination] actually.
Change your code to
strcpy(a.done_exams[i],support);
The
strcpy(a.done_exams[i][0],support);
should be
strcpy(a.done_exams[i],support);
or
strcpy(&a.done_exams[i][0],support);
My advice would be to always compile with compiler warnings turned on. My compiler (gcc) does a very good job of catching the problem and telling you exactly what needs to be done to fix it:
test.c:37:12: warning: incompatible integer to pointer conversion passing 'char' to
parameter of type 'char *'; take the address with & [-Wint-conversion]
strcpy(a.done_exams[i][0],support);
^~~~~~~~~~~~~~~~~~
&
P.S. You are also missing some #includes:
#include <stdlib.h>
#include <string.h>

Resources