I'm writing the following program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "planes.h"
int main(void)
{
plane* planes=NULL;
int size=0;
readPlanes(&planes, &size);
free(planes);
planes=NULL;
return EXIT_SUCCESS;
}
void readPlanes(plane** planes, int* size)
{
char buffer[100]={'\0'};
int airplaneID, modeli;
float fuel;
char modelc;
int invent=0;
int rettest=0;
do{
printf("Enter the number of planes:\n");
fgets(buffer, 100, stdin);
rettest=sscanf(buffer, "%d", size);
if((*size)<=0)
{
printf("Invalid number of planes: enter a non negative number\n");
rettest=0;
}
}while(rettest!=1);
*planes=(plane*)calloc((*size), sizeof(plane*));
for(invent=0; invent<(*size); invent++)
{
planes[invent]=calloc(1, sizeof(plane));
do{
rettest=0;
printf("Enter the airplaneID:\n");
fgets(buffer, 100, stdin);
rettest=sscanf(buffer, "%d", &airplaneID);
if(airplaneID<0)
{
printf("Invalid airplaneID: enter a positive number\n");
rettest=0;
}
}while(rettest!=1);
planes[invent]->airplaneID=airplaneID;
do{
rettest=0;
printf("Enter the model:\n");
fgets(buffer, 100, stdin);
rettest=sscanf(buffer, "%c %d", &modelc, &modeli);
if(modeli<0 || modelc<'A' || modelc>'Z')
{
printf("Invalid model: enter an uppercase letter followed by a non negative number\n");
rettest=0;
}
}while(rettest!=2);
planes[invent]->planemodel.letter=modelc;
planes[invent]->planemodel.number=modeli;
do{
rettest=0;
printf("Enter the fuel:\n");
fgets(buffer, 100, stdin);
rettest=sscanf(buffer, "%f", &fuel);
if(fuel<0.0f)
{
printf("Invalid fuel: enter a non negative number\n");
rettest=0;
}
}while(rettest!=1);
planes[invent]->fuel=fuel;
}
}
The header file is:
#ifndef PLANES_H_INCLUDED
#define PLANES_H_INCLUDED
typedef struct
{
char letter;
int number;
}model;
typedef struct
{
int airplaneID;
model planemodel;
float fuel;
}plane;
void readPlanes(plane**, int*);
int lowestFuel(plane*, int);
void printID(plane*, int, char*);
#endif // PLANES_H_INCLUDED
Anyway, when I run the program with planes=1 the program runs with no problems. However if I try to run it with 2 or more planes, the following error occurs (at the end of the program, after the user entered all the parameters for all the planes):
stack smashing detected: /home/user/Documents/program/bin/Debug/program terminated
Aborted(core dumped)
I have no idea why this is occurring and where is my problem. Can someone help me?
Given planes declared as a plane **, this allocation is incorrect:
*planes=(plane*)calloc((*size), sizeof(plane*));
You are allocating memory to which a plane * will point; inasmuch as you are considering that memory as the storage for an array, the elements of the array (e.g. (*planes)[0]) must therefore be of type plane. You are not allocating enough space for a *size elements of type plane, however; only enough for that many pointers.
A good form to use for allocations specifies the wanted size in terms of the pointer to which the allocation is being assigned; for example,
mytype *p;
p = calloc(n, sizeof (*p));
Observe that the size of the allocation is defined in terms of the size of the thing to which p points, which is almost always what you want, without hard-coding p's type. That not only reduces the scope for errors, it is also flexible with respect to changes to p's type. (Note also that casting the result of malloc / calloc / realloc in C is not only unnecessary, but is regarded by many as poor form.)
In your case, the pointer for which you are allocating is *planes, so the above form would be realized as
*planes = calloc(*size, sizeof(**planes));
You seem to be confused by the double pointer, however. The only reason for it is to enable readPlanes() to modify its caller's local variable. It does not imply a requirement for multiple levels of allocation. In particular, having allocated memory and recorded a pointer to it in *planes, it makes no sense whatever to subsequently allocate more memory and assign it to planes[0], which is the same thing. It makes even less sense to attempt to assign anything to planes[1], however, because as this function was called, planes points to main's pointer planes, and therefore planes[1] points one plane* past that, to ... what? It's not defined, and your program therefore exhibits undefined behavior. That's your stack smashing.
In fact, you don't need the allocations in the loop at all -- you have already (after the first correction) allocated all the space you need. Because you assigned the pointer to *planes, you'll want to access it via that pointer; that means using expressions of the form (*planes)[n] to reference the nth plane. For example,
(*planes)[invent].airplaneID = airplaneID;
Related
This function is supposed to save data to a library.books_count instance of a dynamic array of pointers to structures. Yet it does not. A similar function addexistingBooks() does it flawlessly. What is the problem in realloc()?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char book_name[32];
char book_genre[32];
char author[32];
int page_count;
float price;
}Sbook;
typedef struct
{
char library_name[32];
Sbook * bookp;
int books_count;
}Slib;
void menu(char String[50]);
void addexistingBooks(Slib library, int i);
void addBook(Slib library, int i);
int main()
{
Slib library;
int i=0;
char Choice[30];
printf("Enter amount of books inside the library: ");
scanf("%d", &(library.books_count));
library.bookp = (Sbook *)calloc(library.books_count,sizeof (Sbook));
fflush(stdin);
addexistingBooks(library, i);
menu(Choice);
if(strcmp(Choice,"add")==0)
{
addBook(library, i);
}
free(library.bookp);
return 0;
}
void menu(char String[30])
{
printf("Welcome to the library. If you read about heresy, prepare to be purged \n");
printf("Please choose a command, by writing the appropriate command: \n");
printf("1. Write 'add' to add a book. \n");
printf("2. Write 'remove' to remove a book. \n");
printf("3. Write 'redact' to redact a book. \n");
printf("4. Write 'Sort by criteria' to sort the books, where criteria can stand for: 1.bookname, 2.author, 3.genre, 4.price. \n");
printf("Enter your command: ");
gets(String);
}
void addexistingBooks(Slib library, int i)
{
for(i=0;i<library.books_count;i++)
{
printf("Enter the name of the book: \n");
fgets(library.bookp[i].book_name,32,stdin);
printf("Enter the genre of the book: \n");
fgets(library.bookp[i].book_genre,32,stdin);
printf("Enter the author of the book: \n");
fgets(library.bookp[i].author,32,stdin);
printf("Enter the page count of the book: \n");
scanf("%d", &(library.bookp[i].page_count));
printf("Enter the price of the book: \n");
scanf("%f", &(library.bookp[i].price));
fflush(stdin);
}
}
void addBook(Slib library, int i)
{
(library.books_count)++;
realloc(library.bookp,library.books_count);
fflush(stdin);
if(library.bookp==NULL)
{
exit(1);
}
printf("Enter the name of the book: \n");
fgets(library.bookp[i].book_name,32,stdin);
printf("Enter the genre of the book: \n");
fgets(library.bookp[i].book_genre,32,stdin);
printf("Enter the author of the book: \n");
fgets(library.bookp[i].author,32,stdin);
printf("Enter the page count of the book: \n");
scanf("%d", &(library.bookp[i].page_count));
printf("Enter the price of the book: \n");
scanf("%f", &(library.bookp[i].price));
fflush(stdin);
}
Your code contains several mistakes.
Lets start from the "non-blocking" mistakes. Those that, even if they can be really critical and have to be corrected, are not the real cause of the crash you experience.
The flush of standard input, fflush(stdin); is something that is not defined by the standard, so using it leads to undefined behavior: in some environments it could work, in some other environment it could not work, and there can be environments (the worst ones) in which it seems to work but it is actually harmful. It is recommended to avoid it.
Function gets() is dangerous because it doesn't provide any control on the size of the string inserted by the user, and its use should be avoided.
The issues in the void addBook() function
You try increasing the available space using realloc:
void *realloc(void *ptr, size_t size);
It needs the original pointer and the new size. But you pass library.books_count that is just the number of books. Meaning that, if the library used to contain 4 books, you try to allocate 5 bytes only.
You instead need to allocate library.books_count * sizeof(Sbook) bytes.
Furthermore it returns a new pointer. You need to assign it to the book pointer:
library.bookp = realloc(library.bookp, library.books_count * sizeof(Sbook));
In main() you initialize a i variable, but you never update it, since you store the numbers of books directly in library.books_count.
Then you pass it to addexistingBooks(), and it is redundant because you could use library.books_count itself for the loop, as you actually do. You can use it as the loop variable, but you don't need to have that parameter. Just
void addexistingBooks(Slib library, )
{
int i; /* If your C version is C99 or later, you can declare it in the loop itself */
for(i=0;i<library.books_count;i++)
{
/* Omissis */
}
}
Finally you pass it to addBook(), and not only it is redundant (as you can simply store the new book at index library.books_count-1, but it is actively harmful because you are always updating index 0 (because the value of parameter i is 0).
Although it is possible to pass structures to functions as values, it is not recommended. The first reason is that you will overload the stack of the process (the whole struct will be allocated in the stack area, that is quite big in PC applications but quite limited in embedded systems). The second reason will give you functional problems.
In fact, parameters passed by value are copies of the variables passed to the function. This means that any change made on them will not be reflected to original structures. In your case, the update of library.bookp pointer will not be available outside the function, causing (1) the original structure pointing to an invalid memory address location (becoming a dangling pointer), (2) the leak of the newly allocated memory, that nobody will be able to free().
Pass structures by address, instead, using pointers to structures. addBook() function, considering the i parameter removal, would become as follows
void addBook(Slib *library)
{
int i = library->books_count;
(library->books_count)++;
library->bookp = realloc(library->bookp, library->books_count * sizeof(Sbook));
/* and so on... the value of 'i' is now library->books_count-1 */
}
/* Call from main */
int main()
{
Slib library;
/* Omissis */
menu(Choice);
if(strcmp(Choice,"add")==0)
{
addBook(&library, i);
}
free(library.bookp);
return 0;
}
The definition of realloc function,
void *realloc(void *ptr, size_t size);
So, your realloc function:
realloc(library.bookp,library.books_count);
should change to:
library.bookp = realloc(library.bookp,sizeof(Sbook)*library.books_count);
OT, i see in your menu function, you use gets. It's dangerous, you should use fgets from stdin in stead. See in this link Why is the gets function so dangerous that it should not be used?
I just wrote this snippet of code and have passed values of integers in for when it scans the integer in, but am getting back the memory address of the int towards the end.. how do I display only the number that I just read in instead of it's address? Can I simplify this code snippet even more?
#include <stdlib.h>
#include <stdio.h>
typedef struct building {
char *blockName;
int blockNumber;
} building;
int main() {
building *blockA = (building*)malloc(sizeof(building));
building *blockB = (building*)malloc(sizeof(building));
blockA->blockName = (char*)malloc(25*sizeof(char*));
blockB->blockName = (char*)malloc(25*sizeof(char*));
blockA->blockNumber = (int)malloc(sizeof(int));
blockB->blockNumber = (int)malloc(sizeof(int));
printf("What is the name for your first block: ");
scanf("%s", (*blockA).blockName);
printf("What will be it's number: ");
scanf("%d", (*blockA).blockNumber);
printf("\n");
printf("What is the name for your second block: ");
scanf("%s", (*blockB).blockName);
printf("What will be it's number: ");
scanf("%d", (*blockB).blockNumber);
printf("\n");
printf("Your first block's name is %s. It's number is %d\n", (*blockA).blockName, (*blockA).blockNumber);
printf("Your second block's name is %s. It's number is %d\n", (*blockB).blockName, (*blockB).blockNumber);
printf("\n");
free(blockA->blockName);
free(blockB->blockName);
free(blockA);
free(blockB);
system("pause");
return 0;
}
The member
int blocknumber;
is a plain scalar integer, not a pointer. Use it directly, without allocating memory to it. This line:
blockA->blockNumber = (int)malloc(sizeof(int));
is very suspicious and your compiler should have warned you. (You do compile with warnings enabled, don't you?) You are tyring to store a pointer in an integer value, which will fail on machines where the size of a pointer is greater then the size of an int.
The remedy is not to allocate memory for a scalar, then
scanf("%d", &(*blockB).blockNumber);
(note the &), and then you will have the user input available as:
printf("It's number is %d\n", (*blockB).blockNumber);
On the other hand, the malloc for the string is right, because the string is an array of chars, in this case allocated on the heap and represented by a pointer to the first char.
Since building is defined as
typedef struct building {
char *blockName;
int blockNumber;
} building;
You shouldn't be doing this
blockA->blockNumber = (int)malloc(sizeof(int));
as the line building *blockA = (building*)malloc(sizeof(building)); will already have allocated space on the heap for the int blockNumber:
You can simply assign it
blockA->blockNumber = 1234;
Or prompt the user for it
scanf("%d", &(blockA->blockNumber));
I will be very thankful for looking at my code and telling me whether if I create a structure for which I am dynamically allocating memory, should I dynamically allocate memory also for the structure's elements that are int or double?
As it can be seen in the example below, I use malloc only for those elements of the structure which size can change, namely strings. I tried to use malloc for int or double variables (elements of the structure), but everything worked fine until I tried to use the function printf on them.
It refused to work because printf("%d", [structure]->[int element]) was not correct.
So I changed the code and int and double structure members are processed with the malloc and realloc functions. Is this approach correct?
Would it be expected and even possible to use malloc and realloc for int or double structure members/elements? How to use printf on them later on?
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define LICZBA 2
#define SIZE 256
typedef struct ksiazka{
char * imie;
char * nazwisko;
char * tytul;
int numerkat;
double cena;
}rekord;
rekord * rekordnew(){
rekord *r;
r=malloc(sizeof(rekord));
r->imie=NULL;
r->nazwisko=NULL;
r->tytul=NULL;
r->numerkat=0;
r->cena=0;
return r;
}
void rekordfree(rekord *r){
if (r->imie) free (r->imie);
if (r->nazwisko) free (r-> nazwisko);
if (r-> tytul) free (r-> tytul);
//if (r-> numerkat) free (r->numerkat);
//if (r-> cena) free (r-> cena);
free (r);
}
void wpiszimie(rekord *pr, char im[SIZE]){
(*pr).imie=realloc(pr->imie, strlen(im)+1);
strcpy(pr->imie, im);
}
void wpisznazwisko(rekord *pr, char nazw[SIZE]){
pr->nazwisko=realloc(pr->nazwisko, strlen(nazw)+1);
strcpy(pr->nazwisko, nazw);
}
void wpisztytul(rekord *pr, char tyt[SIZE]){
pr->tytul=realloc(pr->tytul, strlen(tyt)+1);
strcpy(pr->tytul, tyt);
}
void wpisznumerkat(rekord *pr, int numer){
// pr->numerkat=realloc(pr->numerkat, sizeof(int));
pr->numerkat=numer;
}
void wpiszcena(rekord *pr, double cen){
// pr->cena=realloc(pr->cena,sizeof(double));
pr->cena=cen;
}
int main(){
rekord *r[LICZBA];
char bufor[SIZE];
int i, number;
double number2;
for(i=0;i<LICZBA;i++){
r[i]=rekordnew();
}
for(i=0;i<LICZBA;i++){
printf("Podaj tytuł książki");
scanf("%s", bufor);
wpisztytul(r[i],bufor);
printf("Podaj imię autora książki");
if (scanf("%s", bufor)==1)wpiszimie(r[i],bufor);
printf("Podaj nazwisko autora książki");
if (scanf("%s", bufor)==1)wpisznazwisko(r[i],bufor);
printf("Podaj numer katalogowy książki");
if (scanf("%d", &number)==1)wpisznumerkat(r[i],number);
printf("Podaj cenę książki");
if (scanf("%lf", &number2)==1)wpiszcena(r[i],number2);
}
for(i=0;i<LICZBA;i++){
printf("Tytuł książki");
printf("%s", r[i]->tytul);
printf("Imię autora książki");
printf("%s", r[i]->imie);
printf("Nazwisko autora książki");
printf("%s", r[i]->nazwisko);
printf("Numer katalogowy książki");
printf("%d", r[i]->numerkat);
printf("Cena książki");
printf("%lf", r[i]->cena);
}
return 0;
}
I cannot see any severe errors in your code though reasoning about it would be easier for me if you had written it in English.
As you do malloc(sizeof(rekord)) you allocate memory to hold all members of a rekord. That is three char * pointers, an int and a double. You can write to those members immediately, no further allocation is needed. Of course, writing to a char * member is not really useful unless you are assigning it a pointer to some char buffer which you'd in turn obtain via malloc. For the int and double this is neither needed nor possible. So your code is correct here.
A few minor remarks, though:
You should check the return value of malloc. If it fails, it will return NULL. You should check for this (rare) event and handle the error if it happens. Usually, terminating the program will be an appropriate action.
You forgot to call rekordfree at the end.
Using non-ASCII characters in your program source code may or may not work. It should be avoided in portable programs.
Your use of scanf for reading in the strings is a potential security hole as it might overrun the input buffer. Since you are going to store the string in a malloc()ed buffer anyway, I suggest you use getline as a convenient and safe alternative.
Consider adding more whitespace to your output (eg newlines via \n). I guess that even if I understood the language, the output wouldn't be very easy to read as it's all on one line. Printing a space or a tab (\t) at the end of the input prompts might also help improve the user experience.
Is there anyway to write the code without having to initialise the size of the array?
#include <stdio.h>
#define MAXSIZE 100
int main()
{
int i,n;
int num[MAXSIZE];
printf("Enter the value of n\n");
scanf("%d",&n);
printf("Enter the list of integers\n");
for(i=0;i<n;i++);
scanf("%d",&num[i]);
for(i=0;i<n;i++)
printf("%d\t",num[i]);
return 0;
}
I used MAXSIZE since the compiler required me to initialise the size, an error came up everytime I left the size blank. All this because incase the user wants to input more than 100 values, how do i accomodate him?
Is using pointers a better way to write the program?
I tried by changing
#include<stdio.h>
int main()
{
int *num,n,i;
printf("Enter the value of n\n");
scanf("%d",&n);
printf("Enter the list of integers\n");
for(i=0;i<n;i++);
scanf("%d",num+i);
for(i=0;i<n;i++)
printf("%d\t",*(num+i));
return 0;
}
This is giving me a warning saying uninitialised local variable in visual studio and isn't inputting all the numbers. Output is garbage values.
Dev c++ crashes everytime I execute.
Any advice would be helpful, Thanks in advance guys.
If you are using a compiler that supports variable-length arrays (C99 or later, although VLAs are now optional under C2011) and the size of the array is relatively small, you can do the following:
int i, n;
...
scanf( "%d", &n );
int num[n];
// load and print num as before
If your compiler does not support VLAs or the array size is large (more than a few hundred K), then you will want to allocate memory dynamically using either malloc or calloc:
int i, n;
...
scanf( "%d", &n );
int *num = malloc( n * sizeof *num );
// load and print num as before
When you use just a plain pointer, you still need to allocate memory for the array. We can do that with malloc!
int *num,n,i;
printf("Enter the value of n\n");
scanf("%d",&n);
num = malloc(sizeof(*num) * n);
printf("Enter the list of integers\n");
...
Also, even though you are using pointers, you can still write num[i] instead of *(num +i). In fact, those two expressions are always interchangeable, and so you you should use the one that makes your code the most readable.
You can use variable length arrays if you want user to put the size of array (run program in C99 ode. Use the option: -std=c99).
Arrays are used when you need small memory. If you need some large amount of memory then go with pointers and dynamic allocation. When using pointer, initialize it to some memory location before any access to it.
Arrays are NOT pointers !
Their types types are completely different and are treated differently by the compiler.
int *num ;
declares num as pointer to int, which is not pointing to any valid memory address
("uninitialized" as reported by compiler ) . Whatever operation you're doing in second case invokes undefined behaviour
You need to point it to a valid memory location, in this case by using malloc call
num = malloc( sizeof( int ) * n);
I want to store an array of strings , count their length and re-arrange them with length-increasing-order (smallest->larger) using the algorithm mentioned below //
Swap holds a relatively big string to replace the order (when another min is found)
I could use realloc() but I am not considering defend programming yet
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j,N;
printf("\n Input amount of alphanumericals: ");
scanf("%d",&N);
{
int min;
char *swap=(char*)malloc(sizeof(char)*150);
char *A[N],**temp;
temp=A;
for(i=0;i<N;i++){
printf("\nInput %d element:",i+1);
fgets(temp+i,150,STDIN);
}
printf("\n\nData [");
for(i=0;i<N;i++)
printf(" %s",A[i]);
printf(" ]\n\n");
//Ins sort
for(i=0;i<N;i++){
min=i;//Assume current is min
for(j=i+1;j<N;j++){
//Compare assuming min with current
if(strcmp(A[j],A[min])<0){
min=j;
}
//If next is min replace in current position
if(min!=i){
swap=A[i];
A[i]=A[min];
A[min]=swap;
}
}
free(swap);
printf("\nAfter insertion point algorithm\n");
printf("\n\nInsertion Sorted Data [");
for(i=0;i<N;i++)
printf(" %s",A[i]);
printf(" ]");
}
return 0;
}
You are tying to free memory that has not been allocated using malloc:
char *A[N],**temp;
temp = A; // A is an automatic (AKA "stack") variable; now temp points to it as well
free(temp); // Undefined behavior
Inside the loop you are reading with gets into strings that have not been allocated:
gets(temp+i); // That's the same as gets(A[i]); Your A[i]s are unallocated.
As a side note, you should not use gets, because it is a prime source of buffer overruns. Use fgets instead, and pass stdin as the FILE* parameter. scanf with %20s is another alternative to limit the size.
In addition, since i goes from 1 to N, inclusive, this expression references one element past the A array on the last iteration:
gets(temp+i); // Undefined behavior when i==N
EDIT : Why is the code below crashes?
for(i=0;i<N;i++){
printf("\nInput %d element:",i+1);
fgets(temp+i,150,STDIN);
}
The code below crashes because you did not allocate memory for the individual strings:
for(i=0;i<N;i++){
printf("\nInput %d element:",i+1);
temp+i = malloc(151); // No need to multiply by sizeof(char) or cast to char*
fgets(temp+i,150,STDIN);
}
Note that you need to allocate one extra char for the null terminator.
You are not using gets correctly: take a look at its manual page [1]. Moreover, using gets is not recommended: better use fgets.
Also, gets is not allocating the string for you, so when you pass it a char * pointer, the pointer has to point to a valid memory location. Instead, your A[n] is an array of dangling pointers.
Then, why free(temp)? You must call free for each pointer allocated with malloc: not the case for temp.
Finally, please format your code: use indent.
[1] http://linux.die.net/man/3/gets